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
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)
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})
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
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)
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)
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
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
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
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')])
# 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)
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)
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
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 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
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
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
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
# 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()
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)
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]))]})
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
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()
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
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()
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
class TestVariableEliminationMarkov(unittest.TestCase): def setUp(self): # It is just a moralised version of the above Bayesian network so all the results are same. Only factors # are under consideration for inference so this should be fine. self.markov_model = MarkovModel([('A', 'J'), ('R', 'J'), ('J', 'Q'), ('J', 'L'), ('G', 'L'), ('A', 'R'), ('J', 'G')]) factor_a = TabularCPD('A', 2, values=[[0.2], [0.8]]).to_factor() factor_r = TabularCPD('R', 2, values=[[0.4], [0.6]]).to_factor() factor_j = TabularCPD('J', 2, values=[[0.9, 0.6, 0.7, 0.1], [0.1, 0.4, 0.3, 0.9]], evidence=['A', 'R'], evidence_card=[2, 2]).to_factor() factor_q = TabularCPD('Q', 2, values=[[0.9, 0.2], [0.1, 0.8]], evidence=['J'], evidence_card=[2]).to_factor() factor_l = TabularCPD('L', 2, values=[[0.9, 0.45, 0.8, 0.1], [0.1, 0.55, 0.2, 0.9]], evidence=['J', 'G'], evidence_card=[2, 2]).to_factor() factor_g = TabularCPD('G', 2, [[0.6], [0.4]]).to_factor() self.markov_model.add_factors(factor_a, factor_r, factor_j, factor_q, factor_l, factor_g) self.markov_inference = VariableElimination(self.markov_model) # All the values that are used for comparision in the all the tests are # found using SAMIAM (assuming that it is correct ;)) def test_query_single_variable(self): query_result = self.markov_inference.query(['J']) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.416, 0.584])) def test_query_multiple_variable(self): query_result = self.markov_inference.query(['Q', 'J']) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.416, 0.584])) np_test.assert_array_almost_equal(query_result['Q'].values, np.array([0.4912, 0.5088])) def test_query_single_variable_with_evidence(self): query_result = self.markov_inference.query(variables=['J'], evidence={ 'A': 0, 'R': 1 }) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.60, 0.40])) def test_query_multiple_variable_with_evidence(self): query_result = self.markov_inference.query(variables=['J', 'Q'], evidence={ 'A': 0, 'R': 0, 'G': 0, 'L': 1 }) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.818182, 0.181818])) np_test.assert_array_almost_equal(query_result['Q'].values, np.array([0.772727, 0.227273])) def test_query_multiple_times(self): # This just tests that the models are not getting modified while querying them query_result = self.markov_inference.query(['J']) query_result = self.markov_inference.query(['J']) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.416, 0.584])) query_result = self.markov_inference.query(['Q', 'J']) query_result = self.markov_inference.query(['Q', 'J']) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.416, 0.584])) np_test.assert_array_almost_equal(query_result['Q'].values, np.array([0.4912, 0.5088])) query_result = self.markov_inference.query(variables=['J'], evidence={ 'A': 0, 'R': 1 }) query_result = self.markov_inference.query(variables=['J'], evidence={ 'A': 0, 'R': 1 }) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.60, 0.40])) query_result = self.markov_inference.query(variables=['J', 'Q'], evidence={ 'A': 0, 'R': 0, 'G': 0, 'L': 1 }) query_result = self.markov_inference.query(variables=['J', 'Q'], evidence={ 'A': 0, 'R': 0, 'G': 0, 'L': 1 }) np_test.assert_array_almost_equal(query_result['J'].values, np.array([0.818182, 0.181818])) np_test.assert_array_almost_equal(query_result['Q'].values, np.array([0.772727, 0.227273])) def test_max_marginal(self): np_test.assert_almost_equal(self.markov_inference.max_marginal(), 0.1659, decimal=4) def test_max_marginal_var(self): np_test.assert_almost_equal(self.markov_inference.max_marginal(['G']), 0.5714, decimal=4) def test_max_marginal_var1(self): np_test.assert_almost_equal(self.markov_inference.max_marginal( ['G', 'R']), 0.4055, decimal=4) def test_max_marginal_var2(self): np_test.assert_almost_equal(self.markov_inference.max_marginal( ['G', 'R', 'A']), 0.3260, decimal=4) def test_map_query(self): map_query = self.markov_inference.map_query() self.assertDictEqual(map_query, { 'A': 1, 'R': 1, 'J': 1, 'Q': 1, 'G': 0, 'L': 0 }) def test_map_query_with_evidence(self): map_query = self.markov_inference.map_query(['A', 'R', 'L'], { 'J': 0, 'Q': 1, 'G': 0 }) self.assertDictEqual(map_query, {'A': 1, 'R': 0, 'L': 0}) def test_induced_graph(self): induced_graph = self.markov_inference.induced_graph( ['G', 'Q', 'A', 'J', 'L', 'R']) result_edges = sorted([sorted(x) for x in induced_graph.edges()]) self.assertEqual([['A', 'J'], ['A', 'R'], ['G', 'J'], ['G', 'L'], ['J', 'L'], ['J', 'Q'], ['J', 'R'], ['L', 'R']], result_edges) def test_induced_width(self): result_width = self.markov_inference.induced_width( ['G', 'Q', 'A', 'J', 'L', 'R']) self.assertEqual(2, result_width) def tearDown(self): del self.markov_inference del self.markov_model
class 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
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])), ], }, )
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
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
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) )
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')
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])) ] })
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))
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)
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))
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]
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)