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)
def build_graph(self): mm = MarkovModel() mm.add_nodes_from(self.dataset.dataframe.columns) graph_structure_name = list( map(lambda tuple: (self.columns[tuple[0]], self.columns[tuple[1]]), self.graph_structure_index)) mm.add_edges_from(graph_structure_name) self.model = mm.to_bayesian_model()
def to_bn(self, use_mst=False): """ Given the undirected graph, return the directed model corresponding to the minimal I-map. The directed model is placed in the directed attribute. Remarks: This method supports models which are not connected. :param use_mst (boolean): To direct a prelearned model in the directed attribute, direct_mst=False. To obtain the directed model from the maximum spanning tree learned by self.mst, use direct_mst=True. """ # Generate connected components if use_mst: edges = list(self.maxtree.edges()) vertices = list(self.maxtree.nodes) mm = MarkovModel() mm.add_nodes_from(vertices) mm.add_edges_from(edges) bm = mm.to_bayesian_model() self.directed = bm else: connected = list(nx.algorithms.components.connected_components(self.undirected)) # Hold the edges of each connected component as a list(list()) connected_comps = list() # If the graph is not completely connected if len(connected) > 1: self.directed = BayesianModel() for comp in connected: # If the connected component is not a single vertex if len(comp) > 1: edges_to_add = list() temp = MarkovModel() for vert1 in comp: neighbours = list(self.undirected.neighbors(vert1)) for vert2 in neighbours: if not ((vert1, vert2) in edges_to_add) and not ((vert2, vert1) in edges_to_add): edges_to_add.append((vert1, vert2)) temp.add_nodes_from(comp) temp.add_edges_from(edges_to_add) temp_bn = temp.to_bayesian_model() connected_comps.append(temp_bn) else: self.directed.add_nodes_from(comp) for bn in connected_comps: self.directed.add_nodes_from(list(bn.nodes)) self.directed.add_edges_from(list(bn.edges)) else: # If the graph is completely connected, just add all edges to markov model edges = list(self.undirected.edges()) vertices = list(self.undirected.nodes) mm = MarkovModel() mm.add_nodes_from(vertices) mm.add_edges_from(edges) bm = mm.to_bayesian_model() self.directed = bm
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 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
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 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 TestMarkovModelCreation(unittest.TestCase): def setUp(self): self.graph = MarkovModel() def test_class_init_without_data(self): self.assertIsInstance(self.graph, MarkovModel) def test_class_init_with_data_string(self): self.g = MarkovModel([("a", "b"), ("b", "c")]) self.assertListEqual(sorted(self.g.nodes()), ["a", "b", "c"]) self.assertListEqual(hf.recursive_sorted(self.g.edges()), [["a", "b"], ["b", "c"]]) def test_class_init_with_data_nonstring(self): self.g = MarkovModel([(1, 2), (2, 3)]) def test_add_node_string(self): self.graph.add_node("a") self.assertListEqual(list(self.graph.nodes()), ["a"]) def test_add_node_nonstring(self): self.graph.add_node(1) def test_add_nodes_from_string(self): self.graph.add_nodes_from(["a", "b", "c", "d"]) self.assertListEqual(sorted(self.graph.nodes()), ["a", "b", "c", "d"]) def test_add_nodes_from_non_string(self): self.graph.add_nodes_from([1, 2, 3, 4]) def test_add_edge_string(self): self.graph.add_edge("d", "e") self.assertListEqual(sorted(self.graph.nodes()), ["d", "e"]) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [["d", "e"]]) self.graph.add_nodes_from(["a", "b", "c"]) self.graph.add_edge("a", "b") self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [["a", "b"], ["d", "e"]]) def test_add_edge_nonstring(self): self.graph.add_edge(1, 2) def test_add_edge_selfloop(self): self.assertRaises(ValueError, self.graph.add_edge, "a", "a") def test_add_edges_from_string(self): self.graph.add_edges_from([("a", "b"), ("b", "c")]) self.assertListEqual(sorted(self.graph.nodes()), ["a", "b", "c"]) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [["a", "b"], ["b", "c"]]) self.graph.add_nodes_from(["d", "e", "f"]) self.graph.add_edges_from([("d", "e"), ("e", "f")]) self.assertListEqual(sorted(self.graph.nodes()), ["a", "b", "c", "d", "e", "f"]) self.assertListEqual( hf.recursive_sorted(self.graph.edges()), hf.recursive_sorted([("a", "b"), ("b", "c"), ("d", "e"), ("e", "f")]), ) def test_add_edges_from_nonstring(self): self.graph.add_edges_from([(1, 2), (2, 3)]) def test_add_edges_from_self_loop(self): self.assertRaises(ValueError, self.graph.add_edges_from, [("a", "a")]) def test_number_of_neighbors(self): self.graph.add_edges_from([("a", "b"), ("b", "c")]) self.assertEqual(len(list(self.graph.neighbors("b"))), 2) def tearDown(self): del self.graph
import numpy as np from pgmpy.models import MarkovModel from pgmpy.factors.discrete import DiscreteFactor from pgmpy.inference import BeliefPropagation from pgmpy.models import BayesianModel import pandas as pd #when undirected edges are added, the stored node order seems to be flipped at random. #When factors are defined, the node order matters, so explicitly specify the order to #avoid problems, also maybe double check this. G = MarkovModel() G.add_nodes_from(['x1', 'x2', 'x3']) G.add_edges_from([('x1', 'x2'), ('x1', 'x3')]) #G.add_edges_from([('z1', 'z2'), ('z1', 'z3')]) #G.add_edges_from([('x2', 'x1'), ('x3', 'x2')]) #G.add_edges_from([('x1', 'x3'), ('x1', 'x2')]) #G.add_edges_from([('a', 'c'), ('a', 'b')]) #G.add_edge('z1', 'z2') #G.add_edge('z1', 'z3') for edge in G.edges(): print edge #phi = [DiscreteFactor(edge, cardinality=[2, 2], values=np.random.rand(4)) for edge in G.edges()] #####phi = [DiscreteFactor(edge, cardinality=[2, 2], ##### values=np.array([[1,2], ##### [3,4]])) for edge in G.edges()] #G.add_nodes_from(['z1', 'z2']) #G.add_edges_from([('z1', 'z2')])
from pgmpy.models import MarkovModel mm = MarkovModel() mm.add_nodes_from(['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7']) mm.add_edges_from([('x1', 'x3'), ('x1', 'x4'), ('x2', 'x4'), ('x2', 'x5'), ('x3', 'x6'), ('x4', 'x6'), ('x4', 'x7'), ('x5', 'x7')]) mm.get_local_independencies()
from pgmpy.models import MarkovModel mm = MarkovModel() mm.add_nodes_from(['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7']) mm.add_edges_from([('x1', 'x3'), ('x1', 'x4'), ('x2', 'x4'), ('x2', 'x5'), ('x3', 'x6'), ('x4', 'x6'), ('x4', 'x7'), ('x5', 'x7')]) mm.get_local_independencies()
from pgmpy.models import MarkovModel mm = MarkovModel() mm.add_nodes_from(['A', 'B', 'C']) mm.add_edges_from([('A', 'B'), ('B', 'C'), ('C', 'A')]) mm.add_factors(phi1, phi2, phi3) factor_graph_from_mm = mm.to_factor_graph() # While converting a markov model into factor graph, factor nodes # would be automatically added the factor nodes would be in the # form of phi_node1_node2_... factor_graph_from_mm.nodes() factor_graph.edges() # FactorGraph to MarkovModel phi = Factor(['A', 'B', 'C'], [2, 2, 2], np.random.rand(8)) factor_graph = FactorGraph() factor_graph.add_nodes_from(['A', 'B', 'C', 'phi']) factor_graph.add_edges_from([('A', 'phi'), ('B', 'phi'), ('C', 'phi')])
class TestMarkovModelCreation(unittest.TestCase): def setUp(self): self.graph = MarkovModel() def test_class_init_without_data(self): self.assertIsInstance(self.graph, MarkovModel) def test_class_init_with_data_string(self): self.g = MarkovModel([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.g.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.g.edges()), [['a', 'b'], ['b', 'c']]) def test_class_init_with_data_nonstring(self): self.g = MarkovModel([(1, 2), (2, 3)]) def test_add_node_string(self): self.graph.add_node('a') self.assertListEqual(self.graph.nodes(), ['a']) def test_add_node_nonstring(self): self.graph.add_node(1) def test_add_nodes_from_string(self): self.graph.add_nodes_from(['a', 'b', 'c', 'd']) self.assertListEqual(sorted(self.graph.nodes()), ['a', 'b', 'c', 'd']) def test_add_nodes_from_non_string(self): self.graph.add_nodes_from([1, 2, 3, 4]) def test_add_edge_string(self): self.graph.add_edge('d', 'e') self.assertListEqual(sorted(self.graph.nodes()), ['d', 'e']) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [['d', 'e']]) self.graph.add_nodes_from(['a', 'b', 'c']) self.graph.add_edge('a', 'b') self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [['a', 'b'], ['d', 'e']]) def test_add_edge_nonstring(self): self.graph.add_edge(1, 2) def test_add_edge_selfloop(self): self.assertRaises(ValueError, self.graph.add_edge, 'a', 'a') def test_add_edges_from_string(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.graph.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [['a', 'b'], ['b', 'c']]) self.graph.add_nodes_from(['d', 'e', 'f']) self.graph.add_edges_from([('d', 'e'), ('e', 'f')]) self.assertListEqual(sorted(self.graph.nodes()), ['a', 'b', 'c', 'd', 'e', 'f']) self.assertListEqual( hf.recursive_sorted(self.graph.edges()), hf.recursive_sorted([('a', 'b'), ('b', 'c'), ('d', 'e'), ('e', 'f')])) def test_add_edges_from_nonstring(self): self.graph.add_edges_from([(1, 2), (2, 3)]) def test_add_edges_from_self_loop(self): self.assertRaises(ValueError, self.graph.add_edges_from, [('a', 'a')]) def test_number_of_neighbors(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertEqual(len(self.graph.neighbors('b')), 2) 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
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
from pgmpy.factors import Factor import numpy as np phi1 = Factor(['A','B'], [2,2], np.random.rand(4)) phi2 = Factor(['A','B'], [2,2], np.random.rand(4)) phi3 = Factor(['A','B'], [2,2], np.random.rand(4)) factor_graph.add_factors(phi1, phi2, phi3) # Cluster Graph -- Converting Markov model into a factor 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() " Factor nodes after conversions will be automatically added to form 'phi1_node1_node2...' " factor_graph_from_mm.nodes() " ['C', 'B', 'A', phi_A_B', 'phi_B_C', 'phi_A_C' " factor_graph_from_mm.edges() " [('phi_A_B', 'A'), ('phi_A_C', 'A') ... " # Cluster Graph -- Converting Factor Graph to MarkovModel
def __init__(self, m, v=1, y_edges=[], lambda_y_edges=[], lambda_edges=[], allow_abstentions=True, triplets=None, triplet_seed=0): '''Initialize the LabelModel with a graph G. m: number of LF's v: number of Y tasks y_edges: edges between the tasks. (i, j) in y_edges means that there is an edge between y_i and y_j. lambda_y_edges: edges between LF's and tasks. (i, j) in lambda_y_edges means that there is an edge between lambda_i and y_j. If this list is empty, assume that all labeling functions are connected to Y_0. lambda_edges: edges between LF's. (i, j) in lambda_edges means that there is an edge between lambda_i and lambda_j. allow_abstentions: if True, allow abstentions in L_train. triplets: if specified, use these triplets triplet_seed: if triplets not specified, randomly shuffle the nodes with this seed when generating triplets ''' if lambda_y_edges == []: lambda_y_edges = [(i, 0) for i in range(m)] G = MarkovModel() # Add LF nodes G.add_nodes_from(['lambda_{}'.format(i) for i in range(m)]) G.add_nodes_from(['Y_{}'.format(i) for i in range(v)]) # Add edges G.add_edges_from([('Y_{}'.format(start), 'Y_{}'.format(end)) for start, end in y_edges]) G.add_edges_from([('lambda_{}'.format(start), 'Y_{}'.format(end)) for start, end in lambda_y_edges]) G.add_edges_from([('lambda_{}'.format(start), 'lambda_{}'.format(end)) for start, end in lambda_edges]) self.fully_independent_case = lambda_edges == [] self.m = m if m < 3: raise NotImplementedError( "Triplet method needs at least three LF's to run.") self.v = v self.G = G self.junction_tree = self.G.to_junction_tree() self.nodes = sorted(list(self.G.nodes)) self.triplet_seed = triplet_seed if triplet_seed is not None: random.seed(triplet_seed) random.shuffle(self.nodes) self.separator_sets = set([ tuple(sorted(list((set(clique1).intersection(set(clique2)))))) for clique1, clique2 in self.junction_tree.edges ]) self.allow_abstentions = allow_abstentions self.triplets = triplets if not self._check(): raise NotImplementedError( 'Cannot run triplet method for specified 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
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')])
# THIS CODE HAS TO BE RUN ON PYTHON 2 # Otherwise, you will get wrong results 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)
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 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 TestMarkovModelCreation(unittest.TestCase): def setUp(self): self.graph = MarkovModel() def test_class_init_without_data(self): self.assertIsInstance(self.graph, MarkovModel) def test_class_init_with_data_string(self): self.g = MarkovModel([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.g.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.g.edges()), [['a', 'b'], ['b', 'c']]) def test_class_init_with_data_nonstring(self): self.g = MarkovModel([(1, 2), (2, 3)]) def test_add_node_string(self): self.graph.add_node('a') self.assertListEqual(self.graph.nodes(), ['a']) def test_add_node_nonstring(self): self.graph.add_node(1) def test_add_nodes_from_string(self): self.graph.add_nodes_from(['a', 'b', 'c', 'd']) self.assertListEqual(sorted(self.graph.nodes()), ['a', 'b', 'c', 'd']) def test_add_nodes_from_non_string(self): self.graph.add_nodes_from([1, 2, 3, 4]) def test_add_edge_string(self): self.graph.add_edge('d', 'e') self.assertListEqual(sorted(self.graph.nodes()), ['d', 'e']) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [['d', 'e']]) self.graph.add_nodes_from(['a', 'b', 'c']) self.graph.add_edge('a', 'b') self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [['a', 'b'], ['d', 'e']]) def test_add_edge_nonstring(self): self.graph.add_edge(1, 2) def test_add_edge_selfloop(self): self.assertRaises(ValueError, self.graph.add_edge, 'a', 'a') def test_add_edges_from_string(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertListEqual(sorted(self.graph.nodes()), ['a', 'b', 'c']) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), [['a', 'b'], ['b', 'c']]) self.graph.add_nodes_from(['d', 'e', 'f']) self.graph.add_edges_from([('d', 'e'), ('e', 'f')]) self.assertListEqual(sorted(self.graph.nodes()), ['a', 'b', 'c', 'd', 'e', 'f']) self.assertListEqual(hf.recursive_sorted(self.graph.edges()), hf.recursive_sorted([('a', 'b'), ('b', 'c'), ('d', 'e'), ('e', 'f')])) def test_add_edges_from_nonstring(self): self.graph.add_edges_from([(1, 2), (2, 3)]) def test_add_edges_from_self_loop(self): self.assertRaises(ValueError, self.graph.add_edges_from, [('a', 'a')]) def test_number_of_neighbors(self): self.graph.add_edges_from([('a', 'b'), ('b', 'c')]) self.assertEqual(len(self.graph.neighbors('b')), 2) def tearDown(self): del self.graph
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]
import numpy as np from pgmpy.models import MarkovModel nodes = np.load("./Data/nodes.npy").item() all_nodes = nodes['presentFeatures'] + nodes['presentCharacters'] + \ nodes['opponentsTiles'] + nodes['questionsAsked'] + nodes['previousFeatures'] M = MarkovModel() M.add_nodes_from(all_nodes) print(len(M))