def generate_random_fully_connected_MRF(N):
    '''
    Create an MRF with N binary nodes that are all part of the same clique, which
    has 2^N random values

    '''

    G = MarkovModel()

    #create an N nodes
    node_names = ['x%d' % i for i in range(N)]

    G.add_nodes_from(node_names)

    #add an edge between each node and its 4 neighbors, except when the
    #node is on the grid border and has fewer than 4 neighbors
    edges = []

    for i in range(N):
        for j in range(i + 1, N):
            edges.append(('x%d' % i, 'x%d' % j))

    assert (len(edges) == .5 * N**2)

    G.add_edges_from(edges)

    single_factor = DiscreteFactor(
        edges,
        cardinality=[2 for i in range(N)],
        values=np.random.rand(*[2 for i in range(N)]))
    G.add_factors(single_factor)

    return G
Example #2
0
def test_find_MAP():
    print '-' * 80
    G = MarkovModel()
    G.add_nodes_from(['x1', 'x2', 'x3'])
    G.add_edges_from([('x1', 'x2'), ('x1', 'x3')])
    phi = [
        DiscreteFactor(['x2', 'x1'],
                       cardinality=[2, 2],
                       values=np.array([[1.0 / 1, 1.0 / 2], [1.0 / 3,
                                                             1.0 / 4]])),
        DiscreteFactor(['x3', 'x1'],
                       cardinality=[2, 2],
                       values=np.array([[1.0 / 1, 1.0 / 2], [1.0 / 3,
                                                             1.0 / 4]]))
    ]
    #		   DiscreteFactor(['x1'], cardinality=[2],
    #		   values=np.array([2,2]))]
    G.add_factors(*phi)
    print "nodes:", G.nodes()

    bp = BeliefPropagation(G)
    bp.max_calibrate()
    #	bp.calibrate()
    clique_beliefs = bp.get_clique_beliefs()
    print clique_beliefs
    print clique_beliefs[('x1', 'x2')]
    print clique_beliefs[('x1', 'x3')]
    #	print 'partition function should be', np.sum(clique_beliefs[('x1', 'x3')].values)
    phi_query = bp._query(['x1', 'x2', 'x3'], operation='maximize')
    #	phi_query = bp._query(['x1', 'x2', 'x3'], operation='marginalize')
    print phi_query

    sleep(52)
Example #3
0
class TestInferenceBase(unittest.TestCase):
    def setUp(self):
        self.bayesian = BayesianModel([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')])
        a_cpd = TabularCPD('a', 2, [[0.4, 0.6]])
        b_cpd = TabularCPD('b', 2, [[0.2, 0.4], [0.3, 0.4]], evidence='a', evidence_card=[2])
        c_cpd = TabularCPD('c', 2, [[0.1, 0.2], [0.3, 0.4]], evidence='b', evidence_card=[2])
        d_cpd = TabularCPD('d', 2, [[0.4, 0.3], [0.2, 0.1]], evidence='c', evidence_card=[2])
        e_cpd = TabularCPD('e', 2, [[0.3, 0.2], [0.4, 0.1]], evidence='d', evidence_card=[2])
        self.bayesian.add_cpd([a_cpd, b_cpd, c_cpd, d_cpd, e_cpd])

        self.markov = MarkovModel([('a', 'b'), ('b', 'd'), ('a', 'c'), ('c', 'd')])
        factor_1 = Factor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100]))
        factor_2 = Factor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20]))
        factor_3 = Factor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1]))
        factor_4 = Factor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
        self.markov.add_factors(factor_1, factor_2, factor_3, factor_4)

    def test_bayesian_inference_init(self):
        infer_bayesian = Inference(self.bayesian)
        self.assertEqual(set(infer_bayesian.variables), {'a', 'b', 'c', 'd', 'e'})
        self.assertEqual(infer_bayesian.cardinality, {'a': 2, 'b': 2, 'c': 2, 'd': 2, 'e': 2})
        # self.assertEqual(infer_bayesian.factors, {'a': [self.bayesian.get_cpd('a').to_factor(),
        #                                                 self.bayesian.get_cpd('b').to_factor()],
        #                                           'b': [self.bayesian.get_cpd('b').to_factor(),
        #                                                 self.bayesian.get_cpd('c').to_factor()],
        #                                           'c': [self.bayesian.get_cpd('c').to_factor(),
        #                                                 self.bayesian.get_cpd('d').to_factor()],
        #                                           'd': [self.bayesian.get_cpd('d').to_factor(),
        #                                                 self.bayesian.get_cpd('e').to_factor()],
        #                                           'e': [self.bayesian.get_cpd('e').to_factor()]})

    def test_markov_inference_init(self):
        infer_markov = Inference(self.markov)
        self.assertEqual(set(infer_markov.variables), {'a', 'b', 'c', 'd'})
        self.assertEqual(infer_markov.cardinality, {'a': 2, 'b': 2, 'c': 2, 'd': 2})
Example #4
0
class IsingModel:

    def __init__(self, theta, seed=None):

        if seed is not None:
            np.random.seed(seed)
    
        # graph
        self.G = MarkovModel()
    
        for _, row in theta.iterrows():
    
            # unary
            if row["j"]==row["k"]:
                self.G.add_node(str(int(row["j"])))
                theta_jj = row["value"]
                self.G.add_factors(DiscreteFactor([str(int(row["j"]))], [2], 
                np.exp([-theta_jj,theta_jj])))
            # pairwise
            elif row["value"]!=0:
                self.G.add_edge(str(int(row["j"])), str(int(row["k"])))
                theta_jk = row["value"]
                self.G.add_factors(DiscreteFactor([str(int(row["j"])), str(int(row["k"]))], 
                [2, 2], np.exp([theta_jk, -theta_jk, -theta_jk, theta_jk])))

        self.G.check_model()
        self.infer = BeliefPropagation(self.G)
        self.infer.calibrate()

    def get_moments(self):

        p = len(list(self.G.nodes))

        factor_dict = self.infer.get_clique_beliefs()
        mom_matrix = np.zeros([p,p])
        for clique in factor_dict:
            for pair in it.combinations(clique,2):
                moment = factor_dict[clique].marginalize(set(clique).difference(set(pair)),inplace=False)
                moment = moment.normalize(inplace=False)
                pair_int = [int(x) for x in pair]
                moment = moment.values[0,0]+moment.values[1,1]-moment.values[0,1]-moment.values[1,0]
                mom_matrix[pair_int[0],pair_int[1]] = moment
                mom_matrix[pair_int[1],pair_int[0]] = moment
            for unary in it.combinations(clique,1):
                unary_int = [int(x) for x in unary][0]
                moment = factor_dict[clique].marginalize(set(clique).difference(set(unary)),inplace=False).normalize(inplace=False).values
                moment = moment[1]-moment[0]
                mom_matrix[unary_int,unary_int] = moment
        
        return mom_matrix
Example #5
0
def markovmodel_test():
    """
        >>> from ibeis.algo.hots.pgm_ext import *  # NOQA
    """
    from pgmpy.models import MarkovModel
    from pgmpy.factors import Factor
    markovmodel = MarkovModel([('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'A')])
    factor_a_b = Factor(variables=['A', 'B'], cardinality=[2, 2], values=[100, 5, 5, 100])
    factor_b_c = Factor(variables=['B', 'C'], cardinality=[2, 2], values=[100, 3, 2, 4])
    factor_c_d = Factor(variables=['C', 'D'], cardinality=[2, 2], values=[3, 5, 1, 6])
    factor_d_a = Factor(variables=['D', 'A'], cardinality=[2, 2], values=[6, 2, 56, 2])
    markovmodel.add_factors(factor_a_b, factor_b_c, factor_c_d, factor_d_a)

    pgm_viz.show_markov_model(markovmodel)
    pgm_viz.show_junction_tree(markovmodel)
Example #6
0
def test_markovmodel():
    """
        >>> from ibeis.algo.hots.pgm_ext import *  # NOQA
    """
    from pgmpy.models import MarkovModel
    from pgmpy.factors import Factor
    markovmodel = MarkovModel([('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'A')])
    factor_a_b = Factor(variables=['A', 'B'], cardinality=[2, 2], values=[100, 5, 5, 100])
    factor_b_c = Factor(variables=['B', 'C'], cardinality=[2, 2], values=[100, 3, 2, 4])
    factor_c_d = Factor(variables=['C', 'D'], cardinality=[2, 2], values=[3, 5, 1, 6])
    factor_d_a = Factor(variables=['D', 'A'], cardinality=[2, 2], values=[6, 2, 56, 2])
    markovmodel.add_factors(factor_a_b, factor_b_c, factor_c_d, factor_d_a)

    pgm_viz.show_markov_model(markovmodel)
    pgm_viz.show_junction_tree(markovmodel)
Example #7
0
    def to_markov_model(self):
        """
        Converts bayesian model to markov model. The markov model created would
        be the moral graph of the bayesian model.

        Examples
        --------
        >>> from pgmpy.models import BayesianModel
        >>> G = BayesianModel([('diff', 'grade'), ('intel', 'grade'),
        ...                    ('intel', 'SAT'), ('grade', 'letter')])
        >>> mm = G.to_markov_model()
        >>> mm.nodes()
        ['diff', 'grade', 'intel', 'SAT', 'letter']
        >>> mm.edges()
        [('diff', 'intel'), ('diff', 'grade'), ('intel', 'grade'),
        ('intel', 'SAT'), ('grade', 'letter')]
        """
        from pgmpy.models import MarkovModel
        moral_graph = self.moralize()
        mm = MarkovModel(moral_graph.edges())
        mm.add_factors(*[cpd.to_factor() for cpd in self.cpds])

        return mm
Example #8
0
    def to_markov_model(self):
        """
        Converts bayesian model to markov model. The markov model created would
        be the moral graph of the bayesian model.

        Examples
        --------
        >>> from pgmpy.models import BayesianModel
        >>> G = BayesianModel([('diff', 'grade'), ('intel', 'grade'),
        ...                    ('intel', 'SAT'), ('grade', 'letter')])
        >>> mm = G.to_markov_model()
        >>> mm.nodes()
        ['diff', 'grade', 'intel', 'SAT', 'letter']
        >>> mm.edges()
        [('diff', 'intel'), ('diff', 'grade'), ('intel', 'grade'),
        ('intel', 'SAT'), ('grade', 'letter')]
        """
        from pgmpy.models import MarkovModel
        moral_graph = self.moralize()
        mm = MarkovModel(moral_graph.edges())
        mm.add_factors(*[cpd.to_factor() for cpd in self.cpds])

        return mm
Example #9
0
    def to_markov_model(self):
        """
        Converts the factor graph into markov model.

        A markov model contains nodes as random variables and edge between
        two nodes imply interaction between them.

        Examples
        --------
        >>> from pgmpy.models import FactorGraph
        >>> from pgmpy.factors import Factor
        >>> G = FactorGraph()
        >>> G.add_nodes_from(['a', 'b', 'c'])
        >>> G.add_nodes_from(['phi1', 'phi2'])
        >>> G.add_edges_from([('a', 'phi1'), ('b', 'phi1'),
        ...                   ('b', 'phi2'), ('c', 'phi2')])
        >>> phi1 = Factor(['a', 'b'], [2, 2], np.random.rand(4))
        >>> phi2 = Factor(['b', 'c'], [2, 2], np.random.rand(4))
        >>> G.add_factors(phi1, phi2)
        >>> mm = G.to_markov_model()
        """
        from pgmpy.models import MarkovModel
        mm = MarkovModel()

        variable_nodes = self.get_variable_nodes()

        if len(set(self.nodes()) - set(variable_nodes)) != len(self.factors):
            raise ValueError(
                'Factors not associated with all the factor nodes.')

        mm.add_nodes_from(variable_nodes)
        for factor in self.factors:
            scope = factor.scope()
            mm.add_edges_from(itertools.combinations(scope, 2))
            mm.add_factors(factor)

        return mm
Example #10
0
    def to_markov_model(self):
        """
        Converts the factor graph into markov model.

        A markov model contains nodes as random variables and edge between
        two nodes imply interaction between them.

        Examples
        --------
        >>> from pgmpy.models import FactorGraph
        >>> from pgmpy.factors import Factor
        >>> G = FactorGraph()
        >>> G.add_nodes_from(['a', 'b', 'c'])
        >>> phi1 = Factor(['a', 'b'], [2, 2], np.random.rand(4))
        >>> phi2 = Factor(['b', 'c'], [2, 2], np.random.rand(4))
        >>> G.add_factors(phi1, phi2)
        >>> G.add_nodes_from([phi1, phi2])
        >>> G.add_edges_from([('a', phi1), ('b', phi1),
        ...                   ('b', phi2), ('c', phi2)])
        >>> mm = G.to_markov_model()
        """
        from pgmpy.models import MarkovModel
        mm = MarkovModel()

        variable_nodes = self.get_variable_nodes()

        if len(set(self.nodes()) - set(variable_nodes)) != len(self.factors):
            raise ValueError('Factors not associated with all the factor nodes.')

        mm.add_nodes_from(variable_nodes)
        for factor in self.factors:
            scope = factor.scope()
            mm.add_edges_from(itertools.combinations(scope, 2))
            mm.add_factors(factor)

        return mm
class TestUndirectedGraphTriangulation(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_check_clique(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'a')])
        self.assertTrue(self.graph.is_clique(['a', 'b', 'c']))

    def test_is_triangulated(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'a')])
        self.assertTrue(self.graph.is_triangulated())

    def test_triangulation_h1_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H1', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h2_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H2', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h3_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H3', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h4_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h5_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h6_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_cardinality_mismatch_raises_error(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        factor_list = [DiscreteFactor(edge, [2, 2], np.random.rand(4)) for edge in
                       self.graph.edges()]
        self.graph.add_factors(*factor_list)
        self.graph.add_factors(DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6)))
        self.assertRaises(ValueError, self.graph.triangulate)

    def test_triangulation_h1_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H1', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h2_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H2', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h3_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H3', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h4_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h5_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H5', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h6_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = DiscreteFactor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H6', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_copy(self):
        # Setup the original graph
        self.graph.add_nodes_from(['a', 'b'])
        self.graph.add_edges_from([('a', 'b')])

        # Generate the copy
        copy = self.graph.copy()

        # Ensure the copied model is correct
        self.assertTrue(copy.check_model())

        # Basic sanity checks to ensure the graph was copied correctly
        self.assertEqual(len(copy.nodes()), 2)
        self.assertListEqual(copy.neighbors('a'), ['b'])
        self.assertListEqual(copy.neighbors('b'), ['a'])

        # Modify the original graph ...
        self.graph.add_nodes_from(['c'])
        self.graph.add_edges_from([('c', 'b')])

        # ... and ensure none of those changes get propagated
        self.assertEqual(len(copy.nodes()), 2)
        self.assertListEqual(copy.neighbors('a'), ['b'])
        self.assertListEqual(copy.neighbors('b'), ['a'])
        with self.assertRaises(nx.NetworkXError):
            copy.neighbors('c')

        # Ensure the copy has no factors at this point
        self.assertEqual(len(copy.get_factors()), 0)

        # Add factors to the original graph
        phi1 = DiscreteFactor(['a', 'b'], [2, 2], [[0.3, 0.7], [0.9, 0.1]])
        self.graph.add_factors(phi1)

        # The factors should not get copied over
        with self.assertRaises(AssertionError):
            self.assertListEqual(copy.get_factors(), self.graph.get_factors())

        # Create a fresh copy
        del copy
        copy = self.graph.copy()
        self.assertListEqual(copy.get_factors(), self.graph.get_factors())

        # If we change factors in the original, it should not be passed to the clone
        phi1.values = np.array([[0.5, 0.5], [0.5, 0.5]])
        self.assertNotEqual(self.graph.get_factors(), copy.get_factors())

        # Start with a fresh copy
        del copy
        self.graph.add_nodes_from(['d'])
        copy = self.graph.copy()

        # Ensure an unconnected node gets copied over as well
        self.assertEqual(len(copy.nodes()), 4)
        self.assertListEqual(self.graph.neighbors('a'), ['b'])
        self.assertTrue('a' in self.graph.neighbors('b'))
        self.assertTrue('c' in self.graph.neighbors('b'))
        self.assertListEqual(self.graph.neighbors('c'), ['b'])
        self.assertListEqual(self.graph.neighbors('d'), [])

        # Verify that changing the copied model should not update the original
        copy.add_nodes_from(['e'])
        self.assertListEqual(copy.neighbors('e'), [])
        with self.assertRaises(nx.NetworkXError):
            self.graph.neighbors('e')

        # Verify that changing edges in the copy doesn't create edges in the original
        copy.add_edges_from([('d', 'b')])

        self.assertTrue('a' in copy.neighbors('b'))
        self.assertTrue('c' in copy.neighbors('b'))
        self.assertTrue('d' in copy.neighbors('b'))

        self.assertTrue('a' in self.graph.neighbors('b'))
        self.assertTrue('c' in self.graph.neighbors('b'))
        self.assertFalse('d' in self.graph.neighbors('b'))

        # If we remove factors from the copied model, it should not reflect in the original
        copy.remove_factors(phi1)
        self.assertEqual(len(self.graph.get_factors()), 1)
        self.assertEqual(len(copy.get_factors()), 0)

    def tearDown(self):
        del self.graph
Example #12
0
from pgmpy.models import MarkovModel
mm = MarkovModel()
mm.add_nodes_from(['A', 'B', 'C'])
mm.add_edges_from([('A', 'B'), ('B', 'C'), ('C', 'A')])
mm.add_factors(phi1, phi2, phi3)
factor_graph_from_mm = mm.to_factor_graph()
# While converting a markov model into factor graph, factor nodes
# would be automatically added the factor nodes would be in the
# form of phi_node1_node2_...
factor_graph_from_mm.nodes()
factor_graph.edges()
# FactorGraph to MarkovModel
phi = Factor(['A', 'B', 'C'], [2, 2, 2], np.random.rand(8))
factor_graph = FactorGraph()
factor_graph.add_nodes_from(['A', 'B', 'C', 'phi'])
factor_graph.add_edges_from([('A', 'phi'), ('B', 'phi'), ('C', 'phi')])
Example #13
0
    # As cluster belief represents a probability distribution in
    # this case, thus it should be normalized
    cluster_belief.normalize()
    return cluster_belief


phi_a_b = Factor(['a', 'b'], [2, 2], [10, 0.1, 0.1, 10])
phi_a_c = Factor(['a', 'c'], [2, 2], [5, 0.2, 0.2, 5])
phi_c_d = Factor(['c', 'd'], [2, 2], [0.5, 1, 20, 2.5])
phi_d_b = Factor(['d', 'b'], [2, 2], [5, 0.2, 0.2, 5])

# Cluster 1 is a MarkovModel A--B
cluster_1 = MarkovModel([('a', 'b')])

# Adding factors
cluster_1.add_factors(phi_a_b)

# Cluster 2 is a MarkovModel A--C--D--B
cluster_2 = MarkovModel([('a', 'c'), ('c', 'd'), ('d', 'b')])

# Adding factors
cluster_2.add_factors(phi_a_c, phi_c_d, phi_d_b)

# Message passed from cluster 1 -> 2 should the M-Projection of psi1
# as the sepset of cluster 1 and 2 is A, B thus there is no need to
# marginalize psi1
delta_1_2 = compute_message(cluster_1, cluster_2)

# If we want to use any other inference data structure we can pass
# them as an input argument such as: delta_1_2 =
# compute_message(cluster_1, cluster_2, BeliefPropagation)
Example #14
0
from pgmpy.models import MarkovModel
from pgmpy.factors.discrete import DiscreteFactor
from pgmpy.inference import VariableElimination

phi_1 = DiscreteFactor(['A', 'B'], [2, 2], [30, 5, 1, 10])
phi_2 = DiscreteFactor(['B', 'C'], [2, 2], [100, 1, 1, 100])
phi_3 = DiscreteFactor(['C', 'D'], [2, 2], [1, 100, 100, 1])
phi_4 = DiscreteFactor(['D', 'A'], [2, 2], [100, 1, 1, 100])

model = MarkovModel([('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'A')])
model.add_factors(phi_1, phi_2, phi_3, phi_4)
phi = phi_1 * phi_2 * phi_3 * phi_4
Z = model.get_partition_function()
normalized = phi.values / Z

print(normalized)
Example #15
0
class TestMarkovModelMethods(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_get_cardinality(self):

        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        self.assertDictEqual(self.graph.get_cardinality(), {})

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertDictEqual(self.graph.get_cardinality(), {'a': 1, 'b': 2})
        self.graph.remove_factors(phi1)
        self.assertDictEqual(self.graph.get_cardinality(), {})

        phi1 = Factor(['a', 'b'], [2, 2], np.random.rand(4))
        phi2 = Factor(['c', 'd'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertDictEqual(self.graph.get_cardinality(), {'d': 2, 'a': 2, 'b': 2, 'c': 1})

        phi3 = Factor(['d', 'a'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi3)
        self.assertDictEqual(self.graph.get_cardinality(), {'d': 1, 'c': 1, 'b': 2, 'a': 2})

        self.graph.remove_factors(phi1, phi2, phi3)
        self.assertDictEqual(self.graph.get_cardinality(), {})


    def test_get_cardinality_check_cardinality(self):

        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertRaises(ValueError, self.graph.get_cardinality, check_cardinality=True)

        phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi2)
        self.assertRaises(ValueError, self.graph.get_cardinality, check_cardinality=True)

        phi3 = Factor(['c', 'd'], [2, 2], np.random.rand(4))
        self.graph.add_factors(phi3)
        self.assertDictEqual(self.graph.get_cardinality(check_cardinality=True), {'d': 2, 'c': 2, 'b': 2, 'a': 1})


    def test_check_model(self):

        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        phi2 = Factor(['c', 'b'], [3, 2], np.random.rand(6))
        phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12))
        phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4))

        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.assertTrue(self.graph.check_model())

        self.graph.remove_factors(phi1, phi4)
        phi1 = Factor(['a', 'b'], [4, 2], np.random.rand(8))
        self.graph.add_factors(phi1)
        self.assertTrue(self.graph.check_model())

    def test_check_model1(self):
    
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))

        phi2 = Factor(['b', 'c'], [3, 3], np.random.rand(9))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2)
        
        phi3 = Factor(['c', 'a'], [4, 4], np.random.rand(16))
        self.graph.add_factors(phi3)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi3)

        phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6))
        phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12))
        phi4 = Factor(['d', 'a'], [4, 3], np.random.rand(12))
        self.graph.add_factors(phi2, phi3, phi4)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2, phi3, phi4)

        phi2 = Factor(['a', 'b'], [1, 3], np.random.rand(3))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2)

    def test_check_model2(self):
    
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        phi1 = Factor(['a', 'c'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1)

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1, phi2)


        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6))
        phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12))
        phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4))
        phi5 = Factor(['d', 'b'], [4, 2], np.random.rand(8))
        self.graph.add_factors(phi1, phi2, phi3, phi4, phi5)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1, phi2, phi3, phi4, phi5)


    def test_factor_graph(self):
        from pgmpy.models import FactorGraph

        phi1 = Factor(['Alice', 'Bob'], [3, 2], np.random.rand(6))
        phi2 = Factor(['Bob', 'Charles'], [2, 2], np.random.rand(4))
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')])
        self.graph.add_factors(phi1, phi2)

        factor_graph = self.graph.to_factor_graph()
        self.assertIsInstance(factor_graph, FactorGraph)
        self.assertListEqual(sorted(factor_graph.nodes()),
                             ['Alice', 'Bob', 'Charles', 'phi_Alice_Bob',
                              'phi_Bob_Charles'])
        self.assertListEqual(hf.recursive_sorted(factor_graph.edges()),
                             [['Alice', 'phi_Alice_Bob'], ['Bob', 'phi_Alice_Bob'],
                              ['Bob', 'phi_Bob_Charles'], ['Charles', 'phi_Bob_Charles']])
        self.assertListEqual(factor_graph.get_factors(), [phi1, phi2])

    def test_factor_graph_raises_error(self):
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')])
        self.assertRaises(ValueError, self.graph.to_factor_graph)

    def test_junction_tree(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [['a', 'b', 'd'], ['b', 'c', 'd']])
        self.assertEqual(len(junction_tree.edges()), 1)

    def test_junction_tree_single_clique(self):
        from pgmpy.factors import factor_product

        self.graph.add_edges_from([('x1','x2'), ('x2', 'x3'), ('x1', 'x3')])
        phi = [Factor(edge, [2, 2], np.random.rand(4)) for edge in self.graph.edges()]
        self.graph.add_factors(*phi)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [['x1', 'x2', 'x3']])
        factors = junction_tree.get_factors()
        self.assertEqual(factors[0], factor_product(*phi))

    def test_markov_blanket(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        self.assertListEqual(self.graph.markov_blanket('a'), ['b'])
        self.assertListEqual(sorted(self.graph.markov_blanket('b')),
                             ['a', 'c'])

    def test_local_independencies(self):
        from pgmpy.independencies import Independencies

        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        independencies = self.graph.get_local_independencies()

        self.assertIsInstance(independencies, Independencies)
        self.assertEqual(len(independencies.get_assertions()), 2)

        string = ''
        for assertion in sorted(independencies.get_assertions(),
                                key=lambda x: list(x.event1)):
            string += str(assertion) + '\n'

        self.assertEqual(string, '(a _|_ c | b)\n(c _|_ a | b)\n')

    def test_bayesian_model(self):
        from pgmpy.models import BayesianModel
        import networkx as nx

        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        bm = self.graph.to_bayesian_model()
        self.assertIsInstance(bm, BayesianModel)
        self.assertListEqual(sorted(bm.nodes()), ['a', 'b', 'c', 'd'])
        self.assertTrue(nx.is_chordal(bm.to_undirected()))

    def tearDown(self):
        del self.graph
Example #16
0
class TestUndirectedGraphFactorOperations(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_add_factor_raises_error(self):
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles'),
                                   ('Charles', 'Debbie'), ('Debbie', 'Alice')])
        factor = Factor(['Alice', 'Bob', 'John'], [2, 2, 2], np.random.rand(8))
        self.assertRaises(ValueError, self.graph.add_factors, factor)

    def test_add_single_factor(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi = Factor(['a', 'b'], [2, 2], range(4))
        self.graph.add_factors(phi)
        six.assertCountEqual(self, self.graph.factors, [phi])

    def test_add_multiple_factors(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.factors, [phi1, phi2])

    def test_get_factors(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        six.assertCountEqual(self, self.graph.get_factors(), [])
        self.graph.add_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.get_factors(), [phi1, phi2])

    def test_remove_single_factor(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.remove_factors(phi1)
        six.assertCountEqual(self, self.graph.factors, [phi2])

    def test_remove_multiple_factors(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.remove_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.factors, [])

    def test_partition_function(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        self.assertEqual(self.graph.get_partition_function(), 22.0)

    def test_partition_function_raises_error(self):
        self.graph.add_nodes_from(['a', 'b', 'c', 'd'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.get_partition_function)

    def tearDown(self):
        del self.graph
Example #17
0
class TestUndirectedGraphFactorOperations(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_add_factor_raises_error(self):
        self.graph.add_edges_from([
            ("Alice", "Bob"),
            ("Bob", "Charles"),
            ("Charles", "Debbie"),
            ("Debbie", "Alice"),
        ])
        factor = DiscreteFactor(["Alice", "Bob", "John"], [2, 2, 2],
                                np.random.rand(8))
        self.assertRaises(ValueError, self.graph.add_factors, factor)

    def test_add_single_factor(self):
        self.graph.add_nodes_from(["a", "b", "c"])
        phi = DiscreteFactor(["a", "b"], [2, 2], range(4))
        self.graph.add_factors(phi)
        six.assertCountEqual(self, self.graph.factors, [phi])

    def test_add_multiple_factors(self):
        self.graph.add_nodes_from(["a", "b", "c"])
        phi1 = DiscreteFactor(["a", "b"], [2, 2], range(4))
        phi2 = DiscreteFactor(["b", "c"], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.factors, [phi1, phi2])

    def test_get_factors(self):
        self.graph.add_nodes_from(["a", "b", "c"])
        phi1 = DiscreteFactor(["a", "b"], [2, 2], range(4))
        phi2 = DiscreteFactor(["b", "c"], [2, 2], range(4))
        six.assertCountEqual(self, self.graph.get_factors(), [])
        self.graph.add_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.get_factors(), [phi1, phi2])
        six.assertCountEqual(self, self.graph.get_factors("a"), [phi1])

    def test_remove_single_factor(self):
        self.graph.add_nodes_from(["a", "b", "c"])
        phi1 = DiscreteFactor(["a", "b"], [2, 2], range(4))
        phi2 = DiscreteFactor(["b", "c"], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.remove_factors(phi1)
        six.assertCountEqual(self, self.graph.factors, [phi2])

    def test_remove_multiple_factors(self):
        self.graph.add_nodes_from(["a", "b", "c"])
        phi1 = DiscreteFactor(["a", "b"], [2, 2], range(4))
        phi2 = DiscreteFactor(["b", "c"], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.remove_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.factors, [])

    def test_partition_function(self):
        self.graph.add_nodes_from(["a", "b", "c"])
        phi1 = DiscreteFactor(["a", "b"], [2, 2], range(4))
        phi2 = DiscreteFactor(["b", "c"], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.add_edges_from([("a", "b"), ("b", "c")])
        self.assertEqual(self.graph.get_partition_function(), 22.0)

    def test_partition_function_raises_error(self):
        self.graph.add_nodes_from(["a", "b", "c", "d"])
        phi1 = DiscreteFactor(["a", "b"], [2, 2], range(4))
        phi2 = DiscreteFactor(["b", "c"], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.get_partition_function)

    def tearDown(self):
        del self.graph
Example #18
0
class TestMarkovModelMethods(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_get_cardinality(self):

        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])

        self.assertDictEqual(self.graph.get_cardinality(), {})

        phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertDictEqual(self.graph.get_cardinality(), {"a": 1, "b": 2})
        self.graph.remove_factors(phi1)
        self.assertDictEqual(self.graph.get_cardinality(), {})

        phi1 = DiscreteFactor(["a", "b"], [2, 2], np.random.rand(4))
        phi2 = DiscreteFactor(["c", "d"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertDictEqual(self.graph.get_cardinality(), {
            "d": 2,
            "a": 2,
            "b": 2,
            "c": 1
        })

        phi3 = DiscreteFactor(["d", "a"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi3)
        self.assertDictEqual(self.graph.get_cardinality(), {
            "d": 1,
            "c": 1,
            "b": 2,
            "a": 2
        })

        self.graph.remove_factors(phi1, phi2, phi3)
        self.assertDictEqual(self.graph.get_cardinality(), {})

    def test_get_cardinality_with_node(self):

        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])

        phi1 = DiscreteFactor(["a", "b"], [2, 2], np.random.rand(4))
        phi2 = DiscreteFactor(["c", "d"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertEqual(self.graph.get_cardinality("a"), 2)
        self.assertEqual(self.graph.get_cardinality("b"), 2)
        self.assertEqual(self.graph.get_cardinality("c"), 1)
        self.assertEqual(self.graph.get_cardinality("d"), 2)

    def test_check_model(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])

        phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertRaises(ValueError, self.graph.check_model)

        phi2 = DiscreteFactor(["a", "c"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi2)
        self.assertRaises(ValueError, self.graph.check_model)

    def test_check_model1(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2))
        phi2 = DiscreteFactor(["c", "b"], [3, 2], np.random.rand(6))
        phi3 = DiscreteFactor(["c", "d"], [3, 4], np.random.rand(12))
        phi4 = DiscreteFactor(["d", "a"], [4, 1], np.random.rand(4))

        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.assertTrue(self.graph.check_model())

        self.graph.remove_factors(phi1, phi4)
        phi1 = DiscreteFactor(["a", "b"], [4, 2], np.random.rand(8))
        self.graph.add_factors(phi1)
        self.assertTrue(self.graph.check_model())

    def test_check_model2(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])

        phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2))

        phi2 = DiscreteFactor(["b", "c"], [3, 3], np.random.rand(9))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2)

        phi3 = DiscreteFactor(["c", "a"], [4, 4], np.random.rand(16))
        self.graph.add_factors(phi3)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi3)

        phi2 = DiscreteFactor(["b", "c"], [2, 3], np.random.rand(6))
        phi3 = DiscreteFactor(["c", "d"], [3, 4], np.random.rand(12))
        phi4 = DiscreteFactor(["d", "a"], [4, 3], np.random.rand(12))
        self.graph.add_factors(phi2, phi3, phi4)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2, phi3, phi4)

        phi2 = DiscreteFactor(["a", "b"], [1, 3], np.random.rand(3))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2)

    def test_check_model3(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])

        phi1 = DiscreteFactor(["a", "c"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1)

        phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2))
        phi2 = DiscreteFactor(["a", "c"], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1, phi2)

        phi1 = DiscreteFactor(["a", "b"], [1, 2], np.random.rand(2))
        phi2 = DiscreteFactor(["b", "c"], [2, 3], np.random.rand(6))
        phi3 = DiscreteFactor(["c", "d"], [3, 4], np.random.rand(12))
        phi4 = DiscreteFactor(["d", "a"], [4, 1], np.random.rand(4))
        phi5 = DiscreteFactor(["d", "b"], [4, 2], np.random.rand(8))
        self.graph.add_factors(phi1, phi2, phi3, phi4, phi5)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1, phi2, phi3, phi4, phi5)

    def test_factor_graph(self):
        phi1 = DiscreteFactor(["Alice", "Bob"], [3, 2], np.random.rand(6))
        phi2 = DiscreteFactor(["Bob", "Charles"], [2, 2], np.random.rand(4))
        self.graph.add_edges_from([("Alice", "Bob"), ("Bob", "Charles")])
        self.graph.add_factors(phi1, phi2)

        factor_graph = self.graph.to_factor_graph()
        self.assertIsInstance(factor_graph, FactorGraph)
        self.assertListEqual(
            sorted(factor_graph.nodes()),
            ["Alice", "Bob", "Charles", "phi_Alice_Bob", "phi_Bob_Charles"],
        )
        self.assertListEqual(
            hf.recursive_sorted(factor_graph.edges()),
            [
                ["Alice", "phi_Alice_Bob"],
                ["Bob", "phi_Alice_Bob"],
                ["Bob", "phi_Bob_Charles"],
                ["Charles", "phi_Bob_Charles"],
            ],
        )
        self.assertListEqual(factor_graph.get_factors(), [phi1, phi2])

    def test_factor_graph_raises_error(self):
        self.graph.add_edges_from([("Alice", "Bob"), ("Bob", "Charles")])
        self.assertRaises(ValueError, self.graph.to_factor_graph)

    def test_junction_tree(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(
            hf.recursive_sorted(junction_tree.nodes()),
            [["a", "b", "d"], ["b", "c", "d"]],
        )
        self.assertEqual(len(junction_tree.edges()), 1)

    def test_junction_tree_single_clique(self):

        self.graph.add_edges_from([("x1", "x2"), ("x2", "x3"), ("x1", "x3")])
        phi = [
            DiscreteFactor(edge, [2, 2], np.random.rand(4))
            for edge in self.graph.edges()
        ]
        self.graph.add_factors(*phi)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [["x1", "x2", "x3"]])
        factors = junction_tree.get_factors()
        self.assertEqual(factors[0], factor_product(*phi))

    def test_markov_blanket(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c")])
        self.assertListEqual(list(self.graph.markov_blanket("a")), ["b"])
        self.assertListEqual(sorted(self.graph.markov_blanket("b")),
                             ["a", "c"])

    def test_local_independencies(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c")])
        independencies = self.graph.get_local_independencies()
        self.assertIsInstance(independencies, Independencies)
        self.assertEqual(independencies, Independencies(["a", "c", "b"]))

    def test_bayesian_model(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        bm = self.graph.to_bayesian_model()
        self.assertIsInstance(bm, BayesianModel)
        self.assertListEqual(sorted(bm.nodes()), ["a", "b", "c", "d"])
        self.assertTrue(nx.is_chordal(bm.to_undirected()))

    def tearDown(self):
        del self.graph
Example #19
0
def eval_partition_func_random_glass_spin(N):
    '''
	
	Inputs:
		-N: int, generate a random NxN glass spin model

	Outputs:

	'''
    G = MarkovModel()

    #create an NxN grid of nodes
    node_names = ['x%d%d' % (r, c) for r in range(N) for c in range(N)]
    print node_names
    G.add_nodes_from(node_names)

    #add an edge between each node and its 4 neighbors, except when the
    #node is on the grid border and has fewer than 4 neighbors
    edges = []
    for r in range(N):
        for c in range(N):
            if r < N - 1:
                edges.append(('x%d%d' % (r, c), 'x%d%d' % (r + 1, c)))
            if c < N - 1:
                edges.append(('x%d%d' % (r, c), 'x%d%d' % (r, c + 1)))
    assert (len(edges) == 2 * N * (N - 1))
    print edges
    print "number edges =", len(edges)
    G.add_edges_from(edges)

    all_factors = []
    #sample single variable potentials
    STRONG_LOCAL_FIELD = True
    if STRONG_LOCAL_FIELD:
        f = 1  #strong local field
    else:
        f = .1  #weak local field
    for node in node_names:
        #sample in the half open interval [-f, f), gumbel paper actually uses closed interval, shouldn't matter
        theta_i = np.random.uniform(low=-f, high=f)
        factor_vals = np.array([np.exp(-theta_i), np.exp(theta_i)])
        all_factors.append(
            DiscreteFactor([node], cardinality=[2], values=factor_vals))

    #sample two variable potentials
    theta_ij_max = 1.5
    for edge in edges:
        #sample in the half open interval [0, theta_ij_max)
        theta_ij = np.random.uniform(low=0.0, high=theta_ij_max)
        factor_vals = np.array([[np.exp(theta_ij),
                                 np.exp(-theta_ij)],
                                [np.exp(-theta_ij),
                                 np.exp(theta_ij)]])
        all_factors.append(
            DiscreteFactor(edge, cardinality=[2, 2], values=factor_vals))

    G.add_factors(*all_factors)
    #print "factors:", G.get_factors
    #	partition_function_enumeration = G.get_partition_function()
    partition_function_bp = get_partition_function_BP(G)
    #	print "partition function enumeration =", partition_function_enumeration
    print "partition function bp =", partition_function_bp
Example #20
0
from pgmpy.models import MarkovModel
mm = MarkovModel()
mm.add_nodes_from(['A', 'B', 'C'])
mm.add_edges_from([('A', 'B'), ('B', 'C'), ('C', 'A')])
mm.add_factors(phi1, phi2, phi3)
factor_graph_from_mm = mm.to_factor_graph()
# While converting a markov model into factor graph, factor nodes
# would be automatically added the factor nodes would be in the
# form of phi_node1_node2_...
factor_graph_from_mm.nodes()
factor_graph.edges()
# FactorGraph to MarkovModel
phi = Factor(['A', 'B', 'C'], [2, 2, 2],
np.random.rand(8))
factor_graph = FactorGraph()
factor_graph.add_nodes_from(['A', 'B', 'C', 'phi'])
factor_graph.add_edges_from([('A', 'phi'), ('B', 'phi'), ('C', 'phi')])
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
Example #22
0
#	   values=np.array([[1,1],
#	   					[1,1]])) for edge in G.edges()]
#	   values=np.array([[1,1],
#	   					[1,1]])) for edge in G.edges()]

phi = [
    DiscreteFactor(['x2', 'x1'],
                   cardinality=[2, 2],
                   values=np.array([[1, 2], [3, 4]])),
    DiscreteFactor(['x3', 'x1'],
                   cardinality=[2, 2],
                   values=np.array([[1, 2], [3, 4]])),
    DiscreteFactor(['x1'], cardinality=[2], values=np.array([2, 2]))
]

G.add_factors(*phi)
print "factors:", G.get_factors
print "partition function =", G.get_partition_function()


def eval_partition_func_random_glass_spin(N):
    '''
	
	Inputs:
		-N: int, generate a random NxN glass spin model

	Outputs:

	'''
    G = MarkovModel()
Example #23
0
f7 = DiscreteFactor(["contact", "month"],
                    cardinality=[3, 12],
                    values=(276, 607, 18, 199, 129, 576, 73, 38, 529, 345, 64,
                            42, 17, 20, 2, 23, 18, 102, 8, 10, 49, 38, 11, 3,
                            0, 6, 0, 0, 1, 28, 450, 1, 820, 6, 5, 7))
data.groupby(["month", "y"]).size()
f8 = DiscreteFactor(["month", "y"],
                    cardinality=[12, 2],
                    values=(237, 56, 554, 79, 11, 9, 184, 38, 132, 16, 645, 61,
                            476, 55, 28, 21, 1305, 93, 350, 39, 43, 37, 35,
                            17))
data.groupby(["poutcome", "y"]).size()
f9 = DiscreteFactor(["poutcome", "y"],
                    cardinality=[4, 2],
                    values=(427, 63, 159, 38, 46, 83, 3368, 337))
mark.add_factors(f1)
mark.add_factors(f2)
mark.add_factors(f3)
mark.add_factors(f3)
mark.add_factors(f4)
mark.add_factors(f5)
mark.add_factors(f6)
mark.add_factors(f7)
mark.add_factors(f8)
mark.add_factors(f9)

mark.get_local_independencies()

#------------------Calculate inference using Mplp algorithm--------------------

mplp = Mplp(mark)
Example #24
0
class TestUndirectedGraphFactorOperations(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_add_factor_raises_error(self):
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles'),
                                   ('Charles', 'Debbie'), ('Debbie', 'Alice')])
        factor = Factor(['Alice', 'Bob', 'John'], [2, 2, 2], np.random.rand(8))
        self.assertRaises(ValueError, self.graph.add_factors, factor)

    def test_add_single_factor(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi = Factor(['a', 'b'], [2, 2], range(4))
        self.graph.add_factors(phi)
        six.assertCountEqual(self, self.graph.factors, [phi])

    def test_add_multiple_factors(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.factors, [phi1, phi2])

    def test_get_factors(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        six.assertCountEqual(self, self.graph.get_factors(), [])
        self.graph.add_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.get_factors(), [phi1, phi2])

    def test_remove_single_factor(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.remove_factors(phi1)
        six.assertCountEqual(self, self.graph.factors, [phi2])

    def test_remove_multiple_factors(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.remove_factors(phi1, phi2)
        six.assertCountEqual(self, self.graph.factors, [])

    def test_partition_function(self):
        self.graph.add_nodes_from(['a', 'b', 'c'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        self.assertEqual(self.graph.get_partition_function(), 22.0)

    def test_partition_function_raises_error(self):
        self.graph.add_nodes_from(['a', 'b', 'c', 'd'])
        phi1 = Factor(['a', 'b'], [2, 2], range(4))
        phi2 = Factor(['b', 'c'], [2, 2], range(4))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError,
                          self.graph.get_partition_function)

    def tearDown(self):
        del self.graph
class TestInferenceBase(unittest.TestCase):

    def setUp(self):
        self.bayesian = BayesianModel([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')])
        a_cpd = TabularCPD('a', 2, [[0.4, 0.6]])
        b_cpd = TabularCPD('b', 2, [[0.2, 0.4], [0.8, 0.6]], evidence=['a'],
                           evidence_card=[2])
        c_cpd = TabularCPD('c', 2, [[0.1, 0.2], [0.9, 0.8]], evidence=['b'],
                           evidence_card=[2])
        d_cpd = TabularCPD('d', 2, [[0.4, 0.3], [0.6, 0.7]], evidence=['c'],
                           evidence_card=[2])
        e_cpd = TabularCPD('e', 2, [[0.3, 0.2], [0.7, 0.8]], evidence=['d'],
                           evidence_card=[2])
        self.bayesian.add_cpds(a_cpd, b_cpd, c_cpd, d_cpd, e_cpd)

        self.markov = MarkovModel([('a', 'b'), ('b', 'd'), ('a', 'c'), ('c', 'd')])
        factor_1 = DiscreteFactor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100]))
        factor_2 = DiscreteFactor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20]))
        factor_3 = DiscreteFactor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1]))
        factor_4 = DiscreteFactor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
        self.markov.add_factors(factor_1, factor_2, factor_3, factor_4)

    def test_bayesian_inference_init(self):
        infer_bayesian = Inference(self.bayesian)
        self.assertEqual(set(infer_bayesian.variables), {'a', 'b', 'c', 'd', 'e'})
        self.assertEqual(infer_bayesian.cardinality, {'a': 2, 'b': 2, 'c': 2,
                                                      'd': 2, 'e': 2})
        self.assertIsInstance(infer_bayesian.factors, defaultdict)
        self.assertEqual(set(infer_bayesian.factors['a']),
                         set([self.bayesian.get_cpds('a').to_factor(),
                              self.bayesian.get_cpds('b').to_factor()]))
        self.assertEqual(set(infer_bayesian.factors['b']),
                         set([self.bayesian.get_cpds('b').to_factor(),
                              self.bayesian.get_cpds('c').to_factor()]))
        self.assertEqual(set(infer_bayesian.factors['c']),
                         set([self.bayesian.get_cpds('c').to_factor(),
                              self.bayesian.get_cpds('d').to_factor()]))
        self.assertEqual(set(infer_bayesian.factors['d']),
                         set([self.bayesian.get_cpds('d').to_factor(),
                              self.bayesian.get_cpds('e').to_factor()]))
        self.assertEqual(set(infer_bayesian.factors['e']),
                         set([self.bayesian.get_cpds('e').to_factor()]))

    def test_markov_inference_init(self):
        infer_markov = Inference(self.markov)
        self.assertEqual(set(infer_markov.variables), {'a', 'b', 'c', 'd'})
        self.assertEqual(infer_markov.cardinality, {'a': 2, 'b': 2, 'c': 2, 'd': 2})
        self.assertEqual(infer_markov.factors, {'a': [DiscreteFactor(['a', 'b'], [2, 2],
                                                                     np.array([100, 1, 1, 100])),
                                                      DiscreteFactor(['a', 'c'], [2, 2],
                                                                     np.array([40, 30, 100, 20]))],
                                                'b': [DiscreteFactor(['a', 'b'], [2, 2],
                                                                     np.array([100, 1, 1, 100])),
                                                      DiscreteFactor(['b', 'd'], [2, 2],
                                                                     np.array([1, 100, 100, 1]))],
                                                'c': [DiscreteFactor(['a', 'c'], [2, 2],
                                                                     np.array([40, 30, 100, 20])),
                                                      DiscreteFactor(['c', 'd'], [2, 2],
                                                                     np.array([60, 60, 40, 40]))],
                                                'd': [DiscreteFactor(['b', 'd'], [2, 2],
                                                                     np.array([1, 100, 100, 1])),
                                                      DiscreteFactor(['c', 'd'], [2, 2],
                                                                     np.array([60, 60, 40, 40]))]})
Example #26
0
class TestUndirectedGraphTriangulation(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_check_clique(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'a')])
        self.assertTrue(self.graph.check_clique(['a', 'b', 'c']))

    def test_is_triangulated(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'a')])
        self.assertTrue(self.graph.is_triangulated())

    def test_triangulation_h1_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H1', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h2_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H2', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h3_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H3', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h4_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h5_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h6_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(hf.recursive_sorted(self.graph.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_cardinality_mismatch_raises_error(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        factor_list = [Factor(edge, [2, 2], np.random.rand(4)) for edge in
                       self.graph.edges()]
        self.graph.add_factors(*factor_list)
        self.graph.add_factors(Factor(['a', 'b'], [2, 3], np.random.rand(6)))
        self.assertRaises(ValueError, self.graph.triangulate)

    def test_triangulation_h1_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H1', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h2_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H2', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'c'], ['a', 'd'],
                              ['b', 'c'], ['c', 'd']])

    def test_triangulation_h3_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H3', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h4_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h5_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H5', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def test_triangulation_h6_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H6', inplace=True)
        self.assertListEqual(hf.recursive_sorted(H.edges()),
                             [['a', 'b'], ['a', 'd'], ['b', 'c'],
                              ['b', 'd'], ['c', 'd']])

    def tearDown(self):
        del self.graph
Example #27
0
from pgmpy.models import MarkovModel
from pgmpy.factors import Factor
import numpy as np
model = MarkovModel()
# Fig 2.7(a) represents the MarkovModel
model.add_nodes_from(['A', 'B', 'C', 'D'])
model.add_edges_from([('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'A')])
# Adding some factors
phi_A_B = Factor(['A', 'B'], [2, 2], [1, 100, 100, 1])
phi_B_C = Factor(['B', 'C'], [2, 2], [100, 1, 1, 100])
phi_C_D = Factor(['C', 'D'], [2, 2], [1, 100, 100, 1])
phi_D_A = Factor(['D', 'A'], [2, 2], [100, 1, 1, 100])
model.add_factors(phi_A_B, phi_B_C, phi_C_D, phi_D_A)
chordal_graph = model.triangulate()
# Fig 2.9 represents the chordal graph created by triangulation
chordal_graph.edges()
Example #28
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 #29
0
from pgmpy.models import MarkovModel
from pgmpy.factors import Factor
model = MarkovModel()
# Fig 2.7(a) represents the Markov model
model.add_nodes_from(['A', 'B', 'C', 'D'])
model.add_edges_from([('A', 'B'), ('B', 'C'),
                      ('C', 'D'), ('D', 'A')])
# Adding some factors.
phi_A_B = Factor(['A', 'B'], [2, 2], [1, 100,
phi_B_C = Factor(['B', 'C'], [2, 2], [100, 1,
phi_C_D = Factor(['C', 'D'], [2, 2], [1, 100,
phi_D_A = Factor(['D', 'A'], [2, 2], [100, 1,
model.add_factors(phi_A_B, phi_B_C, phi_C_D,
bayesian_model = model.to_bayesian_model()
bayesian_model.edges()
Example #30
0
class TestMarkovModelMethods(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_get_cardinality(self):

        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        self.assertDictEqual(self.graph.get_cardinality(), {})

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertDictEqual(self.graph.get_cardinality(), {'a': 1, 'b': 2})
        self.graph.remove_factors(phi1)
        self.assertDictEqual(self.graph.get_cardinality(), {})

        phi1 = Factor(['a', 'b'], [2, 2], np.random.rand(4))
        phi2 = Factor(['c', 'd'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertDictEqual(self.graph.get_cardinality(), {
            'd': 2,
            'a': 2,
            'b': 2,
            'c': 1
        })

        phi3 = Factor(['d', 'a'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi3)
        self.assertDictEqual(self.graph.get_cardinality(), {
            'd': 1,
            'c': 1,
            'b': 2,
            'a': 2
        })

        self.graph.remove_factors(phi1, phi2, phi3)
        self.assertDictEqual(self.graph.get_cardinality(), {})

    def test_get_cardinality_check_cardinality(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertRaises(ValueError,
                          self.graph.get_cardinality,
                          check_cardinality=True)

        phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi2)
        self.assertRaises(ValueError,
                          self.graph.get_cardinality,
                          check_cardinality=True)

        phi3 = Factor(['c', 'd'], [2, 2], np.random.rand(4))
        self.graph.add_factors(phi3)
        self.assertDictEqual(
            self.graph.get_cardinality(check_cardinality=True), {
                'd': 2,
                'c': 2,
                'b': 2,
                'a': 1
            })

    def test_check_model(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        phi2 = Factor(['c', 'b'], [3, 2], np.random.rand(6))
        phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12))
        phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4))

        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.assertTrue(self.graph.check_model())

        self.graph.remove_factors(phi1, phi4)
        phi1 = Factor(['a', 'b'], [4, 2], np.random.rand(8))
        self.graph.add_factors(phi1)
        self.assertTrue(self.graph.check_model())

    def test_check_model1(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))

        phi2 = Factor(['b', 'c'], [3, 3], np.random.rand(9))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2)

        phi3 = Factor(['c', 'a'], [4, 4], np.random.rand(16))
        self.graph.add_factors(phi3)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi3)

        phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6))
        phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12))
        phi4 = Factor(['d', 'a'], [4, 3], np.random.rand(12))
        self.graph.add_factors(phi2, phi3, phi4)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2, phi3, phi4)

        phi2 = Factor(['a', 'b'], [1, 3], np.random.rand(3))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi2)

    def test_check_model2(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])

        phi1 = Factor(['a', 'c'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1)

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        phi2 = Factor(['a', 'c'], [1, 2], np.random.rand(2))
        self.graph.add_factors(phi1, phi2)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1, phi2)

        phi1 = Factor(['a', 'b'], [1, 2], np.random.rand(2))
        phi2 = Factor(['b', 'c'], [2, 3], np.random.rand(6))
        phi3 = Factor(['c', 'd'], [3, 4], np.random.rand(12))
        phi4 = Factor(['d', 'a'], [4, 1], np.random.rand(4))
        phi5 = Factor(['d', 'b'], [4, 2], np.random.rand(8))
        self.graph.add_factors(phi1, phi2, phi3, phi4, phi5)
        self.assertRaises(ValueError, self.graph.check_model)
        self.graph.remove_factors(phi1, phi2, phi3, phi4, phi5)

    def test_factor_graph(self):
        phi1 = Factor(['Alice', 'Bob'], [3, 2], np.random.rand(6))
        phi2 = Factor(['Bob', 'Charles'], [2, 2], np.random.rand(4))
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')])
        self.graph.add_factors(phi1, phi2)

        factor_graph = self.graph.to_factor_graph()
        self.assertIsInstance(factor_graph, FactorGraph)
        self.assertListEqual(
            sorted(factor_graph.nodes()),
            ['Alice', 'Bob', 'Charles', 'phi_Alice_Bob', 'phi_Bob_Charles'])
        self.assertListEqual(
            hf.recursive_sorted(factor_graph.edges()),
            [['Alice', 'phi_Alice_Bob'], ['Bob', 'phi_Alice_Bob'],
             ['Bob', 'phi_Bob_Charles'], ['Charles', 'phi_Bob_Charles']])
        self.assertListEqual(factor_graph.get_factors(), [phi1, phi2])

    def test_factor_graph_raises_error(self):
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')])
        self.assertRaises(ValueError, self.graph.to_factor_graph)

    def test_junction_tree(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [['a', 'b', 'd'], ['b', 'c', 'd']])
        self.assertEqual(len(junction_tree.edges()), 1)

    def test_junction_tree_single_clique(self):

        self.graph.add_edges_from([('x1', 'x2'), ('x2', 'x3'), ('x1', 'x3')])
        phi = [
            Factor(edge, [2, 2], np.random.rand(4))
            for edge in self.graph.edges()
        ]
        self.graph.add_factors(*phi)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [['x1', 'x2', 'x3']])
        factors = junction_tree.get_factors()
        self.assertEqual(factors[0], factor_product(*phi))

    def test_markov_blanket(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        self.assertListEqual(self.graph.markov_blanket('a'), ['b'])
        self.assertListEqual(sorted(self.graph.markov_blanket('b')),
                             ['a', 'c'])

    def test_local_independencies(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        independencies = self.graph.get_local_independencies()
        self.assertIsInstance(independencies, Independencies)
        self.assertEqual(independencies, Independencies(['a', 'c', 'b']))

    def test_bayesian_model(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        bm = self.graph.to_bayesian_model()
        self.assertIsInstance(bm, BayesianModel)
        self.assertListEqual(sorted(bm.nodes()), ['a', 'b', 'c', 'd'])
        self.assertTrue(nx.is_chordal(bm.to_undirected()))

    def tearDown(self):
        del self.graph
Example #31
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'])
        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
Example #32
0
class TestUndirectedGraphTriangulation(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_check_clique(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'a')])
        self.assertTrue(self.graph.check_clique(['a', 'b', 'c']))

    def test_is_triangulated(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'a')])
        self.assertTrue(self.graph.is_triangulated())

    def test_triangulation_h1_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H1', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['c', 'd']])

    def test_triangulation_h2_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H2', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['c', 'd']])

    def test_triangulation_h3_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H3', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_triangulation_h4_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_triangulation_h5_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_triangulation_h6_inplace(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_cardinality_mismatch_raises_error(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        factor_list = [
            Factor(edge, [2, 2], np.random.rand(4))
            for edge in self.graph.edges()
        ]
        self.graph.add_factors(*factor_list)
        self.graph.add_factors(Factor(['a', 'b'], [2, 3], np.random.rand(6)))
        self.assertRaises(CardinalityError, self.graph.triangulate)

    def test_triangulation_h1_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H1', inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['c', 'd']])

    def test_triangulation_h2_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H2', inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['c', 'd']])

    def test_triangulation_h3_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H3', inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_triangulation_h4_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H4', inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_triangulation_h5_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H5', inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def test_triangulation_h6_create_new(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic='H6', inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [['a', 'b'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']])

    def tearDown(self):
        del self.graph
Example #33
0
class TestInferenceBase(unittest.TestCase):
    def setUp(self):
        self.bayesian = BayesianModel([("a", "b"), ("b", "c"), ("c", "d"),
                                       ("d", "e")])
        a_cpd = TabularCPD("a", 2, [[0.4, 0.6]])
        b_cpd = TabularCPD("b",
                           2, [[0.2, 0.4], [0.8, 0.6]],
                           evidence=["a"],
                           evidence_card=[2])
        c_cpd = TabularCPD("c",
                           2, [[0.1, 0.2], [0.9, 0.8]],
                           evidence=["b"],
                           evidence_card=[2])
        d_cpd = TabularCPD("d",
                           2, [[0.4, 0.3], [0.6, 0.7]],
                           evidence=["c"],
                           evidence_card=[2])
        e_cpd = TabularCPD("e",
                           2, [[0.3, 0.2], [0.7, 0.8]],
                           evidence=["d"],
                           evidence_card=[2])
        self.bayesian.add_cpds(a_cpd, b_cpd, c_cpd, d_cpd, e_cpd)

        self.markov = MarkovModel([("a", "b"), ("b", "d"), ("a", "c"),
                                   ("c", "d")])
        factor_1 = DiscreteFactor(["a", "b"], [2, 2],
                                  np.array([100, 1, 1, 100]))
        factor_2 = DiscreteFactor(["a", "c"], [2, 2],
                                  np.array([40, 30, 100, 20]))
        factor_3 = DiscreteFactor(["b", "d"], [2, 2],
                                  np.array([1, 100, 100, 1]))
        factor_4 = DiscreteFactor(["c", "d"], [2, 2],
                                  np.array([60, 60, 40, 40]))
        self.markov.add_factors(factor_1, factor_2, factor_3, factor_4)

    def test_bayesian_inference_init(self):
        infer_bayesian = Inference(self.bayesian)
        self.assertEqual(set(infer_bayesian.variables),
                         {"a", "b", "c", "d", "e"})
        self.assertEqual(infer_bayesian.cardinality, {
            "a": 2,
            "b": 2,
            "c": 2,
            "d": 2,
            "e": 2
        })
        self.assertIsInstance(infer_bayesian.factors, defaultdict)
        self.assertEqual(
            set(infer_bayesian.factors["a"]),
            set([
                self.bayesian.get_cpds("a").to_factor(),
                self.bayesian.get_cpds("b").to_factor(),
            ]),
        )
        self.assertEqual(
            set(infer_bayesian.factors["b"]),
            set([
                self.bayesian.get_cpds("b").to_factor(),
                self.bayesian.get_cpds("c").to_factor(),
            ]),
        )
        self.assertEqual(
            set(infer_bayesian.factors["c"]),
            set([
                self.bayesian.get_cpds("c").to_factor(),
                self.bayesian.get_cpds("d").to_factor(),
            ]),
        )
        self.assertEqual(
            set(infer_bayesian.factors["d"]),
            set([
                self.bayesian.get_cpds("d").to_factor(),
                self.bayesian.get_cpds("e").to_factor(),
            ]),
        )
        self.assertEqual(
            set(infer_bayesian.factors["e"]),
            set([self.bayesian.get_cpds("e").to_factor()]),
        )

    def test_markov_inference_init(self):
        infer_markov = Inference(self.markov)
        self.assertEqual(set(infer_markov.variables), {"a", "b", "c", "d"})
        self.assertEqual(infer_markov.cardinality, {
            "a": 2,
            "b": 2,
            "c": 2,
            "d": 2
        })
        self.assertEqual(
            infer_markov.factors,
            {
                "a": [
                    DiscreteFactor(["a", "b"], [2, 2],
                                   np.array([100, 1, 1, 100])),
                    DiscreteFactor(["a", "c"], [2, 2],
                                   np.array([40, 30, 100, 20])),
                ],
                "b": [
                    DiscreteFactor(["a", "b"], [2, 2],
                                   np.array([100, 1, 1, 100])),
                    DiscreteFactor(["b", "d"], [2, 2],
                                   np.array([1, 100, 100, 1])),
                ],
                "c": [
                    DiscreteFactor(["a", "c"], [2, 2],
                                   np.array([40, 30, 100, 20])),
                    DiscreteFactor(["c", "d"], [2, 2],
                                   np.array([60, 60, 40, 40])),
                ],
                "d": [
                    DiscreteFactor(["b", "d"], [2, 2],
                                   np.array([1, 100, 100, 1])),
                    DiscreteFactor(["c", "d"], [2, 2],
                                   np.array([60, 60, 40, 40])),
                ],
            },
        )
Example #34
0
class TestUndirectedGraphTriangulation(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_check_clique(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "a")])
        self.assertTrue(self.graph.is_clique(["a", "b", "c"]))

    def test_is_triangulated(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "a")])
        self.assertTrue(self.graph.is_triangulated())

    def test_triangulation_h1_inplace(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic="H1", inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [["a", "b"], ["a", "c"], ["a", "d"], ["b", "c"], ["c", "d"]],
        )

    def test_triangulation_h2_inplace(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic="H2", inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [["a", "b"], ["a", "c"], ["a", "d"], ["b", "c"], ["c", "d"]],
        )

    def test_triangulation_h3_inplace(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic="H3", inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_triangulation_h4_inplace(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic="H4", inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_triangulation_h5_inplace(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic="H4", inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_triangulation_h6_inplace(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        self.graph.triangulate(heuristic="H4", inplace=True)
        self.assertTrue(self.graph.is_triangulated())
        self.assertListEqual(
            hf.recursive_sorted(self.graph.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_cardinality_mismatch_raises_error(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        factor_list = [
            DiscreteFactor(edge, [2, 2], np.random.rand(4))
            for edge in self.graph.edges()
        ]
        self.graph.add_factors(*factor_list)
        self.graph.add_factors(
            DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6)))
        self.assertRaises(ValueError, self.graph.triangulate)

    def test_triangulation_h1_create_new(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic="H1", inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [["a", "b"], ["a", "c"], ["a", "d"], ["b", "c"], ["c", "d"]],
        )

    def test_triangulation_h2_create_new(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic="H2", inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [["a", "b"], ["a", "c"], ["a", "d"], ["b", "c"], ["c", "d"]],
        )

    def test_triangulation_h3_create_new(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic="H3", inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_triangulation_h4_create_new(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic="H4", inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_triangulation_h5_create_new(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic="H5", inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_triangulation_h6_create_new(self):
        self.graph.add_edges_from([("a", "b"), ("b", "c"), ("c", "d"),
                                   ("d", "a")])
        phi1 = DiscreteFactor(["a", "b"], [2, 3], np.random.rand(6))
        phi2 = DiscreteFactor(["b", "c"], [3, 4], np.random.rand(12))
        phi3 = DiscreteFactor(["c", "d"], [4, 5], np.random.rand(20))
        phi4 = DiscreteFactor(["d", "a"], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)
        H = self.graph.triangulate(heuristic="H6", inplace=True)
        self.assertListEqual(
            hf.recursive_sorted(H.edges()),
            [["a", "b"], ["a", "d"], ["b", "c"], ["b", "d"], ["c", "d"]],
        )

    def test_copy(self):
        # Setup the original graph
        self.graph.add_nodes_from(["a", "b"])
        self.graph.add_edges_from([("a", "b")])

        # Generate the copy
        copy = self.graph.copy()

        # Ensure the copied model is correct
        self.assertTrue(copy.check_model())

        # Basic sanity checks to ensure the graph was copied correctly
        self.assertEqual(len(copy.nodes()), 2)
        self.assertListEqual(list(copy.neighbors("a")), ["b"])
        self.assertListEqual(list(copy.neighbors("b")), ["a"])

        # Modify the original graph ...
        self.graph.add_nodes_from(["c"])
        self.graph.add_edges_from([("c", "b")])

        # ... and ensure none of those changes get propagated
        self.assertEqual(len(copy.nodes()), 2)
        self.assertListEqual(list(copy.neighbors("a")), ["b"])
        self.assertListEqual(list(copy.neighbors("b")), ["a"])
        with self.assertRaises(nx.NetworkXError):
            list(copy.neighbors("c"))

        # Ensure the copy has no factors at this point
        self.assertEqual(len(copy.get_factors()), 0)

        # Add factors to the original graph
        phi1 = DiscreteFactor(["a", "b"], [2, 2], [[0.3, 0.7], [0.9, 0.1]])
        self.graph.add_factors(phi1)

        # The factors should not get copied over
        with self.assertRaises(AssertionError):
            self.assertListEqual(list(copy.get_factors()),
                                 self.graph.get_factors())

        # Create a fresh copy
        del copy
        copy = self.graph.copy()
        self.assertListEqual(list(copy.get_factors()),
                             self.graph.get_factors())

        # If we change factors in the original, it should not be passed to the clone
        phi1.values = np.array([[0.5, 0.5], [0.5, 0.5]])
        self.assertNotEqual(self.graph.get_factors(), copy.get_factors())

        # Start with a fresh copy
        del copy
        self.graph.add_nodes_from(["d"])
        copy = self.graph.copy()

        # Ensure an unconnected node gets copied over as well
        self.assertEqual(len(copy.nodes()), 4)
        self.assertListEqual(list(self.graph.neighbors("a")), ["b"])
        self.assertTrue("a" in self.graph.neighbors("b"))
        self.assertTrue("c" in self.graph.neighbors("b"))
        self.assertListEqual(list(self.graph.neighbors("c")), ["b"])
        self.assertListEqual(list(self.graph.neighbors("d")), [])

        # Verify that changing the copied model should not update the original
        copy.add_nodes_from(["e"])
        self.assertListEqual(list(copy.neighbors("e")), [])
        with self.assertRaises(nx.NetworkXError):
            self.graph.neighbors("e")

        # Verify that changing edges in the copy doesn't create edges in the original
        copy.add_edges_from([("d", "b")])

        self.assertTrue("a" in copy.neighbors("b"))
        self.assertTrue("c" in copy.neighbors("b"))
        self.assertTrue("d" in copy.neighbors("b"))

        self.assertTrue("a" in self.graph.neighbors("b"))
        self.assertTrue("c" in self.graph.neighbors("b"))
        self.assertFalse("d" in self.graph.neighbors("b"))

        # If we remove factors from the copied model, it should not reflect in the original
        copy.remove_factors(phi1)
        self.assertEqual(len(self.graph.get_factors()), 1)
        self.assertEqual(len(copy.get_factors()), 0)

    def tearDown(self):
        del self.graph
Example #35
0
class TestMarkovModelMethods(unittest.TestCase):
    def setUp(self):
        self.graph = MarkovModel()

    def test_factor_graph(self):
        from pgmpy.models import FactorGraph

        phi1 = Factor(['Alice', 'Bob'], [3, 2], np.random.rand(6))
        phi2 = Factor(['Bob', 'Charles'], [3, 2], np.random.rand(6))
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')])
        self.graph.add_factors(phi1, phi2)

        factor_graph = self.graph.to_factor_graph()
        self.assertIsInstance(factor_graph, FactorGraph)
        self.assertListEqual(
            sorted(factor_graph.nodes()),
            ['Alice', 'Bob', 'Charles', 'phi_Alice_Bob', 'phi_Bob_Charles'])
        self.assertListEqual(
            hf.recursive_sorted(factor_graph.edges()),
            [['Alice', 'phi_Alice_Bob'], ['Bob', 'phi_Alice_Bob'],
             ['Bob', 'phi_Bob_Charles'], ['Charles', 'phi_Bob_Charles']])
        self.assertListEqual(factor_graph.get_factors(), [phi1, phi2])

    def test_factor_graph_raises_error(self):
        self.graph.add_edges_from([('Alice', 'Bob'), ('Bob', 'Charles')])
        self.assertRaises(ValueError, self.graph.to_factor_graph)

    def test_junction_tree(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [['a', 'b', 'd'], ['b', 'c', 'd']])
        self.assertEqual(len(junction_tree.edges()), 1)

    def test_junction_tree_single_clique(self):
        from pgmpy.factors import factor_product

        self.graph.add_edges_from([('x1', 'x2'), ('x2', 'x3'), ('x1', 'x3')])
        phi = [
            Factor(edge, [2, 2], np.random.rand(4))
            for edge in self.graph.edges()
        ]
        self.graph.add_factors(*phi)

        junction_tree = self.graph.to_junction_tree()
        self.assertListEqual(hf.recursive_sorted(junction_tree.nodes()),
                             [['x1', 'x2', 'x3']])
        factors = junction_tree.get_factors()
        self.assertEqual(factors[0], factor_product(*phi))

    def test_markov_blanket(self):
        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        self.assertListEqual(self.graph.markov_blanket('a'), ['b'])
        self.assertListEqual(sorted(self.graph.markov_blanket('b')),
                             ['a', 'c'])

    def test_local_independencies(self):
        from pgmpy.independencies import Independencies

        self.graph.add_edges_from([('a', 'b'), ('b', 'c')])
        independencies = self.graph.get_local_independencies()

        self.assertIsInstance(independencies, Independencies)
        self.assertEqual(len(independencies.get_assertions()), 2)

        string = ''
        for assertion in sorted(independencies.get_assertions(),
                                key=lambda x: list(x.event1)):
            string += str(assertion) + '\n'

        self.assertEqual(string, '(a _|_ c | b)\n(c _|_ a | b)\n')

    def test_bayesian_model(self):
        from pgmpy.models import BayesianModel
        import networkx as nx

        self.graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                   ('d', 'a')])
        phi1 = Factor(['a', 'b'], [2, 3], np.random.rand(6))
        phi2 = Factor(['b', 'c'], [3, 4], np.random.rand(12))
        phi3 = Factor(['c', 'd'], [4, 5], np.random.rand(20))
        phi4 = Factor(['d', 'a'], [5, 2], np.random.random(10))
        self.graph.add_factors(phi1, phi2, phi3, phi4)

        bm = self.graph.to_bayesian_model()
        self.assertIsInstance(bm, BayesianModel)
        self.assertListEqual(sorted(bm.nodes()), ['a', 'b', 'c', 'd'])
        self.assertTrue(nx.is_chordal(bm.to_undirected()))

    def tearDown(self):
        del self.graph
Example #36
0
from pgmpy.models import MarkovModel
from pgmpy.factors.discrete import DiscreteFactor
from pgmpy.inference import BeliefPropagation
import numpy as np

# Construct a graph
PGM = MarkovModel()
PGM.add_nodes_from(['w1', 'w2', 'w3'])
PGM.add_edges_from([('w1', 'w2'), ('w2', 'w3')])
tr_matrix = np.array([1, 10, 3, 2, 1, 5, 3, 3, 2])
tr_matrix = np.array([1, 2, 3, 10, 1, 3, 3, 5, 2]).reshape(3, 3).T.reshape(-1)
phi = [DiscreteFactor(edge, [3, 3], tr_matrix) for edge in PGM.edges()]
print(phi[0])
print(phi[1])
PGM.add_factors(*phi)

# Calculate partition funtion
Z = PGM.get_partition_function()
print('The partition function is:', Z)

# Calibrate the click
belief_propagation = BeliefPropagation(PGM)
belief_propagation.calibrate()

# Output calibration result, which you should get
query = belief_propagation.query(variables=['w2'])
print('After calibration you should get the following mu(S):\n', query * Z)

# Get marginal distribution over third word
query = belief_propagation.query(variables=['w3'])
class TestUAIWriter(unittest.TestCase):
    def setUp(self):
        self.maxDiff = None
        variables = [
            "kid",
            "bowel-problem",
            "dog-out",
            "family-out",
            "hear-bark",
            "light-on",
        ]
        edges = [
            ["family-out", "dog-out"],
            ["bowel-problem", "dog-out"],
            ["family-out", "light-on"],
            ["dog-out", "hear-bark"],
        ]
        cpds = {
            "kid": np.array([[0.3], [0.7]]),
            "bowel-problem": np.array([[0.01], [0.99]]),
            "dog-out": np.array([[0.99, 0.01, 0.97, 0.03], [0.9, 0.1, 0.3, 0.7]]),
            "family-out": np.array([[0.15], [0.85]]),
            "hear-bark": np.array([[0.7, 0.3], [0.01, 0.99]]),
            "light-on": np.array([[0.6, 0.4], [0.05, 0.95]]),
        }
        states = {
            "kid": ["true", "false"],
            "bowel-problem": ["true", "false"],
            "dog-out": ["true", "false"],
            "family-out": ["true", "false"],
            "hear-bark": ["true", "false"],
            "light-on": ["true", "false"],
        }
        parents = {
            "kid": [],
            "bowel-problem": [],
            "dog-out": ["bowel-problem", "family-out"],
            "family-out": [],
            "hear-bark": ["dog-out"],
            "light-on": ["family-out"],
        }

        self.bayesmodel = BayesianModel()
        self.bayesmodel.add_nodes_from(variables)
        self.bayesmodel.add_edges_from(edges)

        tabular_cpds = []
        for var, values in cpds.items():
            cpd = TabularCPD(
                var,
                len(states[var]),
                values,
                evidence=parents[var],
                evidence_card=[
                    len(states[evidence_var]) for evidence_var in parents[var]
                ],
            )
            tabular_cpds.append(cpd)
        self.bayesmodel.add_cpds(*tabular_cpds)
        self.bayeswriter = UAIWriter(self.bayesmodel)

        edges = {("var_0", "var_1"), ("var_0", "var_2"), ("var_1", "var_2")}
        self.markovmodel = MarkovModel(edges)
        tables = [
            (["var_0", "var_1"], ["4.000", "2.400", "1.000", "0.000"]),
            (
                ["var_0", "var_1", "var_2"],
                [
                    "2.2500",
                    "3.2500",
                    "3.7500",
                    "0.0000",
                    "0.0000",
                    "10.0000",
                    "1.8750",
                    "4.0000",
                    "3.3330",
                    "2.0000",
                    "2.0000",
                    "3.4000",
                ],
            ),
        ]
        domain = {"var_1": "2", "var_2": "3", "var_0": "2"}
        factors = []
        for table in tables:
            variables = table[0]
            cardinality = [int(domain[var]) for var in variables]
            values = list(map(float, table[1]))
            factor = DiscreteFactor(variables, cardinality, values)
            factors.append(factor)
        self.markovmodel.add_factors(*factors)
        self.markovwriter = UAIWriter(self.markovmodel)

    def test_bayes_model(self):
        self.expected_bayes_file = """BAYES
6
2 2 2 2 2 2
6
1 0
3 2 0 1
1 2
2 1 3
1 4
2 2 5

2
0.01 0.99
8
0.99 0.01 0.97 0.03 0.9 0.1 0.3 0.7
2
0.15 0.85
4
0.7 0.3 0.01 0.99
2
0.3 0.7
4
0.6 0.4 0.05 0.95"""
        self.assertEqual(str(self.bayeswriter.__str__()), str(self.expected_bayes_file))

    def test_markov_model(self):
        self.expected_markov_file = """MARKOV
3
2 2 3
2
2 0 1
3 0 1 2

4
4.0 2.4 1.0 0.0
12
2.25 3.25 3.75 0.0 0.0 10.0 1.875 4.0 3.333 2.0 2.0 3.4"""
        self.assertEqual(
            str(self.markovwriter.__str__()), str(self.expected_markov_file)
        )
Example #38
0
def main():
    # maximum size of segments grid cell
    map_size = 50
    # minimum number of pixels to consider segment
    pixels_thresh = 500
    # number of image in the database
    num_images = 70

    # counter for incorrectly classified segments
    num_incorrect = 0
    for idx in range(num_images):
        print('\n\nImage ', idx)

        # read image from disk
        image = cv2.imread('export/image_%04d.jpg' % idx)
        # read ground truth classes
        labels_gt_im = cv2.imread('export/labels_%04d.png' % idx,
                                  cv2.IMREAD_ANYDEPTH).astype(np.int)
        labels_gt_im[labels_gt_im == 65535] = -1
        # read a priori probabilities from classifier
        prob_im = cv2.imread('export/prob_%04d.png' % idx,
                             cv2.IMREAD_ANYDEPTH) / 65535.0
        # read image division into segments
        segments_im = cv2.imread('export/segments_%04d.png' % idx,
                                 cv2.IMREAD_ANYDEPTH)

        # display image
        cv2.imshow('original image', image)
        cv2.waitKey(1)

        # mean R, G, B values for each segment
        mean_rgb = np.zeros([map_size, map_size, 3], dtype=np.float)
        # number of pixels for each segment
        num_pixels = np.zeros([map_size, map_size], dtype=np.uint)
        # a priori probabilities for each segment
        prob = np.zeros([map_size, map_size, 2], dtype=np.float)
        # ground truth classes for each segment
        labels_gt = -1 * np.ones([map_size, map_size], dtype=np.int)
        for y in range(map_size):
            for x in range(map_size):
                # segment identifier
                cur_seg = y * map_size + x
                # indices of pixels belonging to the segment
                cur_pixels = np.nonzero(segments_im == cur_seg)

                if len(cur_pixels[0]) > 0:
                    num_pixels[y, x] = len(cur_pixels[0])
                    # flip because opencv stores images as BGR by default
                    mean_rgb[y,
                             x, :] = np.flip(np.mean(image[cur_pixels],
                                                     axis=0))
                    # average results from the classifier - should not be necessary
                    prob[y, x, 0] = np.mean(prob_im[cur_pixels])
                    prob[y, x, 1] = 1.0 - prob[y, x, 0]
                    # labeling boundaries don't have to be aligned with segments boundaties
                    # count which label is the most common in this segment
                    labels_unique, count = np.unique(labels_gt_im[cur_pixels],
                                                     return_counts=True)
                    labels_gt[y, x] = labels_unique[np.argmax(count)]
                    pass

        # build model
        # PUT YOUR CODE HERE

        nodes = []
        # if segment size is bigger than pixels_thresh, add current segment to node list
        for y in range(map_size):
            for x in range(map_size):
                if num_pixels[y, x] > pixels_thresh:
                    nodes.append("s_" + str(y) + "_" + str(x))

        factors_unary = []
        # if segment size is bigger than pixels_thresh, add unary factor of segment to list
        for y in range(map_size):
            for x in range(map_size):
                if num_pixels[y, x] > pixels_thresh:
                    # print(prob[y, x] * 0.9/1 + 0.05)
                    cur_f = create_factor(["s_" + str(y) + "_" + str(x)],
                                          [[0, 1]], [0.945212], [unary_feat],
                                          [prob[y, x]])
                    factors_unary.append(cur_f)

        factors_pairway = []
        edges_pairway = []
        # if segment size is bigger than pixels_thresh and his neighbour too, add pairway factor to list
        for y in range(map_size - 1):
            for x in range(map_size - 1):
                if num_pixels[y, x] > pixels_thresh:

                    # check neighnour to the right
                    if num_pixels[y, x + 1] > pixels_thresh:
                        cur_f = create_factor([
                            "s_" + str(y) + "_" + str(x),
                            "s_" + str(y) + "_" + str(x + 1)
                        ], [[0, 1], [0, 1]], [1.86891, 1.07741, 1.89271], [
                            pairway_feat_red, pairway_feat_green,
                            pairway_feat_blue
                        ], [mean_rgb[y, x], mean_rgb[y, x + 1]])
                        factors_pairway.append(cur_f)
                        edges_pairway.append(
                            ("s_" + str(y) + "_" + str(x),
                             "s_" + str(y) + "_" + str(x + 1)))
                    # check neighbour under
                    if num_pixels[y + 1, x] > pixels_thresh:
                        cur_f = create_factor([
                            "s_" + str(y) + "_" + str(x),
                            "s_" + str(y + 1) + "_" + str(x)
                        ], [[0, 1], [0, 1]], [1.86891, 1.07741, 1.89271], [
                            pairway_feat_red, pairway_feat_green,
                            pairway_feat_blue
                        ], [mean_rgb[y, x], mean_rgb[y + 1, x]])
                        factors_pairway.append(cur_f)
                        edges_pairway.append(
                            ("s_" + str(y) + "_" + str(x),
                             "s_" + str(y + 1) + "_" + str(x)))

        # use Markov model, because MPLP doesn't support factor graphs
        G = MarkovModel()
        G.add_nodes_from(nodes)  # add nodes
        G.add_factors(*factors_unary)  # add unary factors
        G.add_factors(*factors_pairway)  # add pairway factors
        G.add_edges_from(edges_pairway)  # add edges

        # check if everything is ok
        print("Check model: ", G.check_model())

        # ------------------

        # inferred image pixels
        labels_infer = -1 * np.ones([map_size, map_size], dtype=np.int)

        # read results of the inference
        # PUT YOUR CODE HERE
        mplp_infer = Mplp(G)
        q = mplp_infer.map_query()

        segment_cnt = 0
        for y in range(map_size):
            for x in range(map_size):

                if num_pixels[y, x] > pixels_thresh:
                    val = q["s_" + str(y) + "_" + str(x)]
                    rv = None
                    if val == factors_unary[segment_cnt].values[0]:
                        rv = 0
                    else:
                        rv = 1
                    labels_infer[y, x] = rv

                    segment_cnt += 1

        # ------------------

        labels_class = -1 * np.ones([map_size, map_size], dtype=np.int)

        for y in range(map_size - 1):
            for x in range(map_size - 1):
                if num_pixels[y, x] > pixels_thresh:
                    # label as the class with the highest probability
                    if prob[y, x, 0] >= 0.5:
                        labels_class[y, x] = 0
                    else:
                        labels_class[y, x] = 1

        # count correct pixels
        cnt_corr = np.sum(
            np.logical_and(labels_gt == labels_infer, labels_gt != -1))

        print('Accuracy = ', cnt_corr / np.sum(labels_gt != -1))
        num_incorrect += np.sum(labels_gt != -1) - cnt_corr

        # transfer results for segments onto image
        labels_infer_im = -1 * np.ones_like(labels_gt_im)
        labels_class_im = -1 * np.ones_like(labels_gt_im)
        for y in range(map_size - 1):
            for x in range(map_size - 1):
                if labels_infer[y, x] >= 0:
                    cur_seg = y * map_size + x
                    cur_pixels = np.nonzero(segments_im == cur_seg)

                    labels_infer_im[cur_pixels] = labels_infer[y, x]
                    labels_class_im[cur_pixels] = labels_class[y, x]

        # class 0 - green, class 1 - red in BGR
        colors = np.array([[0, 255, 0], [0, 0, 255]], dtype=np.uint8)

        image_infer = image.copy()
        image_class = image.copy()
        image_gt = image.copy()

        # color pixels according to label
        for l in range(2):
            image_infer[labels_infer_im == l] = colors[l]
            image_class[labels_class_im == l] = colors[l]
            image_gt[labels_gt_im == l] = colors[l]

        # show inferred, classified, and gt image by blending the original image with the colored one
        image_infer_vis = (0.75 * image + 0.25 * image_infer).astype(np.uint8)
        cv2.imshow('inferred', image_infer_vis)

        image_class_vis = (0.75 * image + 0.25 * image_class).astype(np.uint8)
        cv2.imshow('classified', image_class_vis)

        image_gt_vis = (0.75 * image + 0.25 * image_gt).astype(np.uint8)
        cv2.imshow('ground truth', image_gt_vis)

        # uncomment to stop after each image
        # cv2.waitKey()
        cv2.waitKey(10)

    print('Incorrectly inferred ', num_incorrect, ' segments')
Example #39
0
class TestInferenceBase(unittest.TestCase):
    def setUp(self):
        self.bayesian = BayesianModel([('a', 'b'), ('b', 'c'), ('c', 'd'),
                                       ('d', 'e')])
        a_cpd = TabularCPD('a', 2, [[0.4, 0.6]])
        b_cpd = TabularCPD('b',
                           2, [[0.2, 0.4], [0.3, 0.4]],
                           evidence='a',
                           evidence_card=[2])
        c_cpd = TabularCPD('c',
                           2, [[0.1, 0.2], [0.3, 0.4]],
                           evidence='b',
                           evidence_card=[2])
        d_cpd = TabularCPD('d',
                           2, [[0.4, 0.3], [0.2, 0.1]],
                           evidence='c',
                           evidence_card=[2])
        e_cpd = TabularCPD('e',
                           2, [[0.3, 0.2], [0.4, 0.1]],
                           evidence='d',
                           evidence_card=[2])
        self.bayesian.add_cpds(a_cpd, b_cpd, c_cpd, d_cpd, e_cpd)

        self.markov = MarkovModel([('a', 'b'), ('b', 'd'), ('a', 'c'),
                                   ('c', 'd')])
        factor_1 = Factor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100]))
        factor_2 = Factor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20]))
        factor_3 = Factor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1]))
        factor_4 = Factor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
        self.markov.add_factors(factor_1, factor_2, factor_3, factor_4)

    def test_bayesian_inference_init(self):
        infer_bayesian = Inference(self.bayesian)
        self.assertEqual(set(infer_bayesian.variables),
                         {'a', 'b', 'c', 'd', 'e'})
        self.assertEqual(infer_bayesian.cardinality, {
            'a': 2,
            'b': 2,
            'c': 2,
            'd': 2,
            'e': 2
        })
        self.assertIsInstance(infer_bayesian.factors, defaultdict)
        self.assertEqual(
            set(infer_bayesian.factors['a']),
            set([
                self.bayesian.get_cpds('a').to_factor(),
                self.bayesian.get_cpds('b').to_factor()
            ]))
        self.assertEqual(
            set(infer_bayesian.factors['b']),
            set([
                self.bayesian.get_cpds('b').to_factor(),
                self.bayesian.get_cpds('c').to_factor()
            ]))
        self.assertEqual(
            set(infer_bayesian.factors['c']),
            set([
                self.bayesian.get_cpds('c').to_factor(),
                self.bayesian.get_cpds('d').to_factor()
            ]))
        self.assertEqual(
            set(infer_bayesian.factors['d']),
            set([
                self.bayesian.get_cpds('d').to_factor(),
                self.bayesian.get_cpds('e').to_factor()
            ]))
        self.assertEqual(set(infer_bayesian.factors['e']),
                         set([self.bayesian.get_cpds('e').to_factor()]))

    def test_markov_inference_init(self):
        infer_markov = Inference(self.markov)
        self.assertEqual(set(infer_markov.variables), {'a', 'b', 'c', 'd'})
        self.assertEqual(infer_markov.cardinality, {
            'a': 2,
            'b': 2,
            'c': 2,
            'd': 2
        })
        self.assertEqual(
            infer_markov.factors, {
                'a': [
                    Factor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100])),
                    Factor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20]))
                ],
                'b': [
                    Factor(['a', 'b'], [2, 2], np.array([100, 1, 1, 100])),
                    Factor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1]))
                ],
                'c': [
                    Factor(['a', 'c'], [2, 2], np.array([40, 30, 100, 20])),
                    Factor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
                ],
                'd': [
                    Factor(['b', 'd'], [2, 2], np.array([1, 100, 100, 1])),
                    Factor(['c', 'd'], [2, 2], np.array([60, 60, 40, 40]))
                ]
            })
Example #40
0
class TestUAIWriter(unittest.TestCase):
    def setUp(self):
        self.maxDiff = None
        edges = [['family-out', 'dog-out'], ['bowel-problem', 'dog-out'],
                 ['family-out', 'light-on'], ['dog-out', 'hear-bark']]
        cpds = {
            'bowel-problem': np.array([[0.01], [0.99]]),
            'dog-out': np.array([[0.99, 0.01, 0.97, 0.03],
                                 [0.9, 0.1, 0.3, 0.7]]),
            'family-out': np.array([[0.15], [0.85]]),
            'hear-bark': np.array([[0.7, 0.3], [0.01, 0.99]]),
            'light-on': np.array([[0.6, 0.4], [0.05, 0.95]])
        }
        states = {
            'bowel-problem': ['true', 'false'],
            'dog-out': ['true', 'false'],
            'family-out': ['true', 'false'],
            'hear-bark': ['true', 'false'],
            'light-on': ['true', 'false']
        }
        parents = {
            'bowel-problem': [],
            'dog-out': ['bowel-problem', 'family-out'],
            'family-out': [],
            'hear-bark': ['dog-out'],
            'light-on': ['family-out']
        }

        self.bayesmodel = BayesianModel(edges)

        tabular_cpds = []
        for var, values in cpds.items():
            cpd = TabularCPD(var,
                             len(states[var]),
                             values,
                             evidence=parents[var],
                             evidence_card=[
                                 len(states[evidence_var])
                                 for evidence_var in parents[var]
                             ])
            tabular_cpds.append(cpd)
        self.bayesmodel.add_cpds(*tabular_cpds)
        self.bayeswriter = UAIWriter(self.bayesmodel)

        edges = {('var_0', 'var_1'), ('var_0', 'var_2'), ('var_1', 'var_2')}
        self.markovmodel = MarkovModel(edges)
        tables = [(['var_0', 'var_1'], ['4.000', '2.400', '1.000', '0.000']),
                  (['var_0', 'var_1', 'var_2'], [
                      '2.2500', '3.2500', '3.7500', '0.0000', '0.0000',
                      '10.0000', '1.8750', '4.0000', '3.3330', '2.0000',
                      '2.0000', '3.4000'
                  ])]
        domain = {'var_1': '2', 'var_2': '3', 'var_0': '2'}
        factors = []
        for table in tables:
            variables = table[0]
            cardinality = [int(domain[var]) for var in variables]
            values = list(map(float, table[1]))
            factor = Factor(variables, cardinality, values)
            factors.append(factor)
        self.markovmodel.add_factors(*factors)
        self.markovwriter = UAIWriter(self.markovmodel)

    def test_bayes_model(self):
        self.expected_bayes_file = """BAYES
5
2 2 2 2 2
5
1 0
3 2 0 1
1 2
2 1 3
2 2 4

2
0.01 0.99
8
0.99 0.01 0.97 0.03 0.9 0.1 0.3 0.7
2
0.15 0.85
4
0.7 0.3 0.01 0.99
4
0.6 0.4 0.05 0.95"""
        self.assertEqual(str(self.bayeswriter.__str__()),
                         str(self.expected_bayes_file))

    def test_markov_model(self):
        self.expected_markov_file = """MARKOV
3
2 2 3
2
2 0 1
3 0 1 2

4
4.0 2.4 1.0 0.0
12
2.25 3.25 3.75 0.0 0.0 10.0 1.875 4.0 3.333 2.0 2.0 3.4"""
        self.assertEqual(str(self.markovwriter.__str__()),
                         str(self.expected_markov_file))
Example #41
0
class TestGibbsSampling(unittest.TestCase):
    def setUp(self):
        # A test Bayesian model
        diff_cpd = TabularCPD('diff', 2, [[0.6], [0.4]])
        intel_cpd = TabularCPD('intel', 2, [[0.7], [0.3]])
        grade_cpd = TabularCPD('grade',
                               3,
                               [[0.3, 0.05, 0.9, 0.5], [0.4, 0.25, 0.08, 0.3],
                                [0.3, 0.7, 0.02, 0.2]],
                               evidence=['diff', 'intel'],
                               evidence_card=[2, 2])
        self.bayesian_model = BayesianModel()
        self.bayesian_model.add_nodes_from(['diff', 'intel', 'grade'])
        self.bayesian_model.add_edges_from([('diff', 'grade'),
                                            ('intel', 'grade')])
        self.bayesian_model.add_cpds(diff_cpd, intel_cpd, grade_cpd)

        # A test Markov model
        self.markov_model = MarkovModel([('A', 'B'), ('C', 'B'), ('B', 'D')])
        factor_ab = DiscreteFactor(['A', 'B'], [2, 3], [1, 2, 3, 4, 5, 6])
        factor_cb = DiscreteFactor(['C', 'B'], [4, 3],
                                   [3, 1, 4, 5, 7, 8, 1, 3, 10, 4, 5, 6])
        factor_bd = DiscreteFactor(['B', 'D'], [3, 2], [5, 7, 2, 1, 9, 3])
        self.markov_model.add_factors(factor_ab, factor_cb, factor_bd)

        self.gibbs = GibbsSampling(self.bayesian_model)

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

    @patch('pgmpy.sampling.GibbsSampling._get_kernel_from_bayesian_model',
           autospec=True)
    @patch('pgmpy.models.MarkovChain.__init__', autospec=True)
    def test_init_bayesian_model(self, init, get_kernel):
        model = MagicMock(spec_set=BayesianModel)
        gibbs = GibbsSampling(model)
        init.assert_called_once_with(gibbs)
        get_kernel.assert_called_once_with(gibbs, model)

    @patch('pgmpy.sampling.GibbsSampling._get_kernel_from_markov_model',
           autospec=True)
    def test_init_markov_model(self, get_kernel):
        model = MagicMock(spec_set=MarkovModel)
        gibbs = GibbsSampling(model)
        get_kernel.assert_called_once_with(gibbs, model)

    def test_get_kernel_from_bayesian_model(self):
        gibbs = GibbsSampling()
        gibbs._get_kernel_from_bayesian_model(self.bayesian_model)
        self.assertListEqual(list(gibbs.variables),
                             self.bayesian_model.nodes())
        self.assertDictEqual(gibbs.cardinalities, {
            'diff': 2,
            'intel': 2,
            'grade': 3
        })

    def test_get_kernel_from_markov_model(self):
        gibbs = GibbsSampling()
        gibbs._get_kernel_from_markov_model(self.markov_model)
        self.assertListEqual(list(gibbs.variables), self.markov_model.nodes())
        self.assertDictEqual(gibbs.cardinalities, {
            'A': 2,
            'B': 3,
            'C': 4,
            'D': 2
        })

    def test_sample(self):
        start_state = [State('diff', 0), State('intel', 0), State('grade', 0)]
        sample = self.gibbs.sample(start_state, 2)
        self.assertEquals(len(sample), 2)
        self.assertEquals(len(sample.columns), 3)
        self.assertIn('diff', sample.columns)
        self.assertIn('intel', sample.columns)
        self.assertIn('grade', sample.columns)
        self.assertTrue(set(sample['diff']).issubset({0, 1}))
        self.assertTrue(set(sample['intel']).issubset({0, 1}))
        self.assertTrue(set(sample['grade']).issubset({0, 1, 2}))

    @patch("pgmpy.sampling.GibbsSampling.random_state", autospec=True)
    def test_sample_less_arg(self, random_state):
        self.gibbs.state = None
        random_state.return_value = [
            State('diff', 0),
            State('intel', 0),
            State('grade', 0)
        ]
        sample = self.gibbs.sample(size=2)
        random_state.assert_called_once_with(self.gibbs)
        self.assertEqual(len(sample), 2)

    def test_generate_sample(self):
        start_state = [State('diff', 0), State('intel', 0), State('grade', 0)]
        gen = self.gibbs.generate_sample(start_state, 2)
        samples = [sample for sample in gen]
        self.assertEqual(len(samples), 2)
        self.assertEqual(
            {samples[0][0].var, samples[0][1].var, samples[0][2].var},
            {'diff', 'intel', 'grade'})
        self.assertEqual(
            {samples[1][0].var, samples[1][1].var, samples[1][2].var},
            {'diff', 'intel', 'grade'})

    @patch("pgmpy.sampling.GibbsSampling.random_state", autospec=True)
    def test_generate_sample_less_arg(self, random_state):
        self.gibbs.state = None
        gen = self.gibbs.generate_sample(size=2)
        samples = [sample for sample in gen]
        random_state.assert_called_once_with(self.gibbs)
        self.assertEqual(len(samples), 2)
Example #42
0
    # As cluster belief represents a probability distribution in
    # this case, thus it should be normalized
    cluster_belief.normalize()
    return cluster_belief


phi_a_b = Factor(['a', 'b'], [2, 2], [10, 0.1, 0.1, 10])
phi_a_c = Factor(['a', 'c'], [2, 2], [5, 0.2, 0.2, 5])
phi_c_d = Factor(['c', 'd'], [2, 2], [0.5, 1, 20, 2.5])
phi_d_b = Factor(['d', 'b'], [2, 2], [5, 0.2, 0.2, 5])

# Cluster 1 is a MarkovModel A--B
cluster_1 = MarkovModel([('a', 'b')])

# Adding factors
cluster_1.add_factors(phi_a_b)

# Cluster 2 is a MarkovModel A--C--D--B
cluster_2 = MarkovModel([('a', 'c'), ('c', 'd'), ('d', 'b')])

# Adding factors
cluster_2.add_factors(phi_a_c, phi_c_d, phi_d_b)

# Message passed from cluster 1 -> 2 should the M-Projection of psi1
# as the sepset of cluster 1 and 2 is A, B thus there is no need to
# marginalize psi1
delta_1_2 = compute_message(cluster_1, cluster_2)

# If we want to use any other inference data structure we can pass
# them as an input argument such as: delta_1_2 =
# compute_message(cluster_1, cluster_2, BeliefPropagation)
class TestUAIWriter(unittest.TestCase):
    def setUp(self):
        self.maxDiff = None
        edges = [['family-out', 'dog-out'],
                 ['bowel-problem', 'dog-out'],
                 ['family-out', 'light-on'],
                 ['dog-out', 'hear-bark']]
        cpds = {'bowel-problem': np.array([[0.01],
                                           [0.99]]),
                'dog-out': np.array([[0.99, 0.01, 0.97, 0.03],
                                     [0.9, 0.1, 0.3, 0.7]]),
                'family-out': np.array([[0.15],
                                        [0.85]]),
                'hear-bark': np.array([[0.7, 0.3],
                                       [0.01, 0.99]]),
                'light-on': np.array([[0.6, 0.4],
                                      [0.05, 0.95]])}
        states = {'bowel-problem': ['true', 'false'],
                  'dog-out': ['true', 'false'],
                  'family-out': ['true', 'false'],
                  'hear-bark': ['true', 'false'],
                  'light-on': ['true', 'false']}
        parents = {'bowel-problem': [],
                   'dog-out': ['bowel-problem', 'family-out'],
                   'family-out': [],
                   'hear-bark': ['dog-out'],
                   'light-on': ['family-out']}

        self.bayesmodel = BayesianModel(edges)

        tabular_cpds = []
        for var, values in cpds.items():
            cpd = TabularCPD(var, len(states[var]), values,
                             evidence=parents[var],
                             evidence_card=[len(states[evidence_var])
                                            for evidence_var in parents[var]])
            tabular_cpds.append(cpd)
        self.bayesmodel.add_cpds(*tabular_cpds)
        self.bayeswriter = UAIWriter(self.bayesmodel)

        edges = {('var_0', 'var_1'), ('var_0', 'var_2'), ('var_1', 'var_2')}
        self.markovmodel = MarkovModel(edges)
        tables = [(['var_0', 'var_1'],
                   ['4.000', '2.400', '1.000', '0.000']),
                  (['var_0', 'var_1', 'var_2'],
                   ['2.2500', '3.2500', '3.7500', '0.0000', '0.0000', '10.0000',
                    '1.8750', '4.0000', '3.3330', '2.0000', '2.0000', '3.4000'])]
        domain = {'var_1': '2', 'var_2': '3', 'var_0': '2'}
        factors = []
        for table in tables:
            variables = table[0]
            cardinality = [int(domain[var]) for var in variables]
            values = list(map(float, table[1]))
            factor = DiscreteFactor(variables, cardinality, values)
            factors.append(factor)
        self.markovmodel.add_factors(*factors)
        self.markovwriter = UAIWriter(self.markovmodel)

    def test_bayes_model(self):
        self.expected_bayes_file = """BAYES
5
2 2 2 2 2
5
1 0
3 2 0 1
1 2
2 1 3
2 2 4

2
0.01 0.99
8
0.99 0.01 0.97 0.03 0.9 0.1 0.3 0.7
2
0.15 0.85
4
0.7 0.3 0.01 0.99
4
0.6 0.4 0.05 0.95"""
        self.assertEqual(str(self.bayeswriter.__str__()), str(self.expected_bayes_file))

    def test_markov_model(self):
        self.expected_markov_file = """MARKOV
3
2 2 3
2
2 0 1
3 0 1 2

4
4.0 2.4 1.0 0.0
12
2.25 3.25 3.75 0.0 0.0 10.0 1.875 4.0 3.333 2.0 2.0 3.4"""
        self.assertEqual(str(self.markovwriter.__str__()), str(self.expected_markov_file))
Example #44
0
class generate(object):
    def __init__(self, adj_mat=None, struct=None):
        DEBUG = False
        self.G = MarkovModel()
        self.n_nodes = adj_mat.shape[0]
        if DEBUG: print 'struct', struct
        if struct == 'complete':
            self._complete_graph(adj_mat)
        if struct == 'nodes':
            self._nodes_only(adj_mat)
        if struct is None:
            self._import_adj(adj_mat)
        self._ising_factors(Wf=5, Wi=5, f_type='mixed')
        if DEBUG: print 'generate_init', self.G, self.G.nodes()

    def get_model(self):
        return self.G

    def _complete_graph(self, adj_mat):
        """
        generate the complete graph over len(adj_mat)
        """

        self._nodes_only(adj_mat)
        for i in range(self.n_nodes):
            self.G.add_edges_from([(i, j)
                                   for j in range(self.n_nodes)])

    def _import_adj(self, adj_mat):
        """
        add nodes and edges to graph
        adj_mat - square matrix, numpy array like
        """
        DEBUG = False
        assert (adj_mat is not None), "can't import empty adj mat"
        # add nodes
        self._nodes_only(adj_mat)
        # add edges
        for i in range(self.n_nodes):
            edges_list = ([(i, j)
                           for j in range(self.n_nodes)
                           if adj_mat[i][j]])
            if DEBUG: print edges_list
            self.G.add_edges_from(edges_list)
            if DEBUG: print len(self.G)

    def _nodes_only(self, adj_mat):
        """
        add nodes to graph
        adj_mat - aquare matrix, numpy array like
        """
        global DEBUG
        assert (adj_mat is not None), "can't import empty adj mat"
        assert (self.n_nodes == adj_mat.shape[1]), "adj_mat is not sqaure"
        self.G.add_nodes_from([i for i in range(self.n_nodes)])
        if DEBUG: print '_nodes_only', [i for i in range(self.n_nodes)]
        if DEBUG: print '_nodes_only print G', self.G.nodes()
        assert (self.n_nodes == len(self.G)), "graph size is incosistent with adj_mat"

    def _ising_factors(self, Wf=1, Wi=1, f_type='mixed'):
        """
        Add ising-like factors to model graph
        cardinality is the number of possible values
        in our case we have boolean nodes, thus cardinality = 2
        Wf   =  \theta_i     = ~U[-Wf, Wf] 
        type =  'mixed'      = ~U[-Wi,Wi]
                'attractive' = ~U[0,Wi]
        """
        self._field_factors(Wf)
        self._interact_factors(Wi, f_type)

    def _field_factors(self, w, states=2):
        """
            this function assigns factor for single node
            currently states=2 for ising model generation
        """

        for i in self.G.nodes():
            phi_i = Factor([i], [states], self._wf(w, states))
            self.G.add_factors(phi_i)

    def _interact_factors(self, w, f_type, states=2):
        """
            this function assigns factor for two interacting nodes
            currently states=2 for ising model generation
        """

        for e in self.G.edges():
            # if DEBUG: print 'interact_factors edges,states, values',e,[e[0],
            #  e[1]],len(e)*[states], self._wi(w, f_type, states)
            phi_ij = Factor([e[0], e[1]], [states] * len(e), self._wi(w, f_type, states))
            self.G.add_factors(phi_ij)

    def _wf(self, w, k):
        """
            generate field factor
        """
        # if DEBUG: print 'w',type(w),w
        return np.random.uniform(low=-1 * w, high=w, size=k)

    def _wi(self, w, f_type, k):
        """
            generate interaction factor
            current support only for k=2
        """
        # if DEBUG: print 'w',type(w),w
        a_ij = np.random.uniform(low=-1 * w, high=w)
        if f_type == 'mixed':
            dis_aij = -a_ij
        else:  # f_type == 'attractive':
            dis_aij = 0
        # else:
        #     print 'f_type error'
        return [a_ij, dis_aij, dis_aij, a_ij]
Example #45
0
class TestGibbsSampling(unittest.TestCase):
    def setUp(self):
        # A test Bayesian model
        diff_cpd = TabularCPD('diff', 2, [[0.6], [0.4]])
        intel_cpd = TabularCPD('intel', 2, [[0.7], [0.3]])
        grade_cpd = TabularCPD('grade', 3, [[0.3, 0.05, 0.9, 0.5], [0.4, 0.25, 0.08, 0.3], [0.3, 0.7, 0.02, 0.2]],
                               evidence=['diff', 'intel'], evidence_card=[2, 2])
        self.bayesian_model = BayesianModel()
        self.bayesian_model.add_nodes_from(['diff', 'intel', 'grade'])
        self.bayesian_model.add_edges_from([('diff', 'grade'), ('intel', 'grade')])
        self.bayesian_model.add_cpds(diff_cpd, intel_cpd, grade_cpd)

        # A test Markov model
        self.markov_model = MarkovModel([('A', 'B'), ('C', 'B'), ('B', 'D')])
        factor_ab = Factor(['A', 'B'], [2, 3], [1, 2, 3, 4, 5, 6])
        factor_cb = Factor(['C', 'B'], [4, 3], [3, 1, 4, 5, 7, 8, 1, 3, 10, 4, 5, 6])
        factor_bd = Factor(['B', 'D'], [3, 2], [5, 7, 2, 1, 9, 3])
        self.markov_model.add_factors(factor_ab, factor_cb, factor_bd)

        self.gibbs = GibbsSampling(self.bayesian_model)

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

    @patch('pgmpy.inference.Sampling.GibbsSampling._get_kernel_from_bayesian_model', autospec=True)
    @patch('pgmpy.models.MarkovChain.__init__', autospec=True)
    def test_init_bayesian_model(self, init, get_kernel):
        model = MagicMock(spec_set=BayesianModel)
        gibbs = GibbsSampling(model)
        init.assert_called_once_with(gibbs)
        get_kernel.assert_called_once_with(gibbs, model)

    @patch('pgmpy.inference.Sampling.GibbsSampling._get_kernel_from_markov_model', autospec=True)
    def test_init_markov_model(self, get_kernel):
        model = MagicMock(spec_set=MarkovModel)
        gibbs = GibbsSampling(model)
        get_kernel.assert_called_once_with(gibbs, model)

    def test_get_kernel_from_bayesian_model(self):
        gibbs = GibbsSampling()
        gibbs._get_kernel_from_bayesian_model(self.bayesian_model)
        self.assertListEqual(list(gibbs.variables), self.bayesian_model.nodes())
        self.assertDictEqual(gibbs.cardinalities, {'diff': 2, 'intel': 2, 'grade': 3})

    def test_get_kernel_from_markov_model(self):
        gibbs = GibbsSampling()
        gibbs._get_kernel_from_markov_model(self.markov_model)
        self.assertListEqual(list(gibbs.variables), self.markov_model.nodes())
        self.assertDictEqual(gibbs.cardinalities, {'A': 2, 'B': 3, 'C': 4, 'D': 2})

    def test_sample(self):
        start_state = [State('diff', 0), State('intel', 0), State('grade', 0)]
        sample = self.gibbs.sample(start_state, 2)
        self.assertEquals(len(sample), 2)
        self.assertEquals(len(sample.columns), 3)
        self.assertIn('diff', sample.columns)
        self.assertIn('intel', sample.columns)
        self.assertIn('grade', sample.columns)
        self.assertTrue(set(sample['diff']).issubset({0, 1}))
        self.assertTrue(set(sample['intel']).issubset({0, 1}))
        self.assertTrue(set(sample['grade']).issubset({0, 1, 2}))


    @patch("pgmpy.inference.Sampling.GibbsSampling.random_state", autospec=True)
    def test_sample_less_arg(self, random_state):
        self.gibbs.state = None
        random_state.return_value = [State('diff', 0), State('intel', 0), State('grade', 0)]
        sample = self.gibbs.sample(size=2)
        random_state.assert_called_once_with(self.gibbs)
        self.assertEqual(len(sample), 2)


    def test_generate_sample(self):
        start_state = [State('diff', 0), State('intel', 0), State('grade', 0)]
        gen = self.gibbs.generate_sample(start_state, 2)
        samples = [sample for sample in gen]
        self.assertEqual(len(samples), 2)
        self.assertEqual({samples[0][0].var, samples[0][1].var, samples[0][2].var}, {'diff', 'intel', 'grade'})
        self.assertEqual({samples[1][0].var, samples[1][1].var, samples[1][2].var}, {'diff', 'intel', 'grade'})


    @patch("pgmpy.inference.Sampling.GibbsSampling.random_state", autospec=True)
    def test_generate_sample_less_arg(self, random_state):
        self.gibbs.state = None
        gen = self.gibbs.generate_sample(size=2)
        samples = [sample for sample in gen]
        random_state.assert_called_once_with(self.gibbs)
        self.assertEqual(len(samples), 2)