def test_deepcopy(): """ Tests deep copy of join tree. :return: None """ a = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn = Bbn().add_node(a).add_node(b) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) lhs = InferenceController.apply(bbn) rhs = copy.deepcopy(lhs) lhs_nodes, rhs_nodes = lhs.get_nodes(), rhs.get_nodes() lhs_edges, rhs_edges = lhs.get_edges(), rhs.get_edges() lhs_neighbors, rhs_neighbors = lhs.neighbors, rhs.neighbors lhs_evidences, rhs_evidences = lhs.evidences, rhs.evidences lhs_potentials, rhs_potentials = lhs.potentials, rhs.potentials assert len(lhs_nodes) == len(rhs_nodes) assert len(lhs_edges) == len(rhs_edges) assert len(lhs_neighbors) == len(rhs_neighbors) assert len(lhs_evidences) == len(rhs_evidences) assert len(lhs_potentials) == len(rhs_potentials) list(lhs.get_nodes())[0].nodes[0].variable.values[0] = 'true' lhs_v = list(lhs.get_nodes())[0].nodes[0].variable.values[0] rhs_v = list(rhs.get_nodes())[0].nodes[0].variable.values[0] assert lhs_v != rhs_v
def test_inference_4(): """ Tests inference on simple customized graph. :return: None. """ a = BbnNode(Variable(0, 'a', ['on', 'off']), [0.7, 0.3]) b = BbnNode(Variable(1, 'b', ['on', 'off']), [0.4, 0.6]) c = BbnNode(Variable(2, 'c', ['on', 'off']), [0.9, 0.1, 0.3, 0.7, 0.5, 0.5, 0.1, 0.9]) e = BbnNode(Variable(4, 'e', ['on', 'off']), [0.6, 0.4, 0.2, 0.8]) bbn = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_node(e) \ .add_edge(Edge(a, c, EdgeType.DIRECTED)) \ .add_edge(Edge(b, c, EdgeType.DIRECTED)) \ .add_edge(Edge(c, e, EdgeType.DIRECTED)) join_tree = InferenceController.apply(bbn) expected = { 'a': [0.7, 0.3], 'b': [0.4, 0.6], 'c': [0.456, 0.544], 'e': [0.3824, 0.6176] } __validate_posterior__(expected, join_tree)
def test_sampling_with_rejection(): """ Tests sampling a serial graph with rejection and evidence set. :return: None. """ a = BbnNode(Variable(0, 'a', ['on', 'off']), [0.5, 0.5]) b = BbnNode(Variable(1, 'b', ['on', 'off']), [0.5, 0.5, 0.4, 0.6]) c = BbnNode(Variable(2, 'c', ['on', 'off']), [0.7, 0.3, 0.2, 0.8]) bbn = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) \ .add_edge(Edge(b, c, EdgeType.DIRECTED)) sampler = LogicSampler(bbn) n_samples = 10000 samples = pd.DataFrame( sampler.get_samples(evidence={0: 'on'}, n_samples=n_samples, seed=37)) samples.columns = ['a', 'b', 'c'] assert n_samples == samples.shape[0] assert 3 == samples.shape[1] s_a = samples.a.value_counts() s_b = samples.b.value_counts() s_c = samples.c.value_counts() s_a = s_a / s_a.sum() s_b = s_b / s_b.sum() s_c = s_c / s_c.sum() s_a = s_a.sort_index().values s_b = s_b.sort_index().values s_c = s_c.sort_index().values assert_almost_equal(s_a, np.array([1.0])) assert_almost_equal(s_b, np.array([0.5006, 0.4994])) assert_almost_equal(s_c, np.array([0.5521, 0.4479])) join_tree = InferenceController.apply(bbn) ev = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('a')) \ .with_evidence('on', 1.0) \ .build() join_tree.set_observation(ev) posteriors = join_tree.get_posteriors() assert_almost_equal(s_a, np.array([posteriors['a']['on']]), decimal=1) assert_almost_equal(s_b, np.array( [posteriors['b']['off'], posteriors['b']['on']]), decimal=1) assert_almost_equal(s_c, np.array( [posteriors['c']['off'], posteriors['c']['on']]), decimal=1)
def __init__(self, bbn): """ ctor :param bbn: Bayesian belief network. """ self.bbn = bbn self.jt = InferenceController.apply(bbn)
def test_from_data_simple(): """ Tests create BBN from data. :return: None. """ a = BbnNode(Variable(0, 'a', ['on', 'off']), [0.5, 0.5]) b = BbnNode(Variable(1, 'b', ['on', 'off']), [0.5, 0.5, 0.4, 0.6]) c = BbnNode(Variable(2, 'c', ['on', 'off']), [0.7, 0.3, 0.2, 0.8]) bbn1 = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) \ .add_edge(Edge(b, c, EdgeType.DIRECTED)) sampler = LogicSampler(bbn1) samples = sampler.get_samples(n_samples=10000, seed=37) i2n = {n.variable.id: n.variable.name for n in bbn1.get_nodes()} samples = pd.DataFrame(samples).rename(columns=i2n) parents = { 'a': [], 'b': ['a'], 'c': ['b'] } bbn2 = Factory.from_data(parents, samples) join_tree1 = InferenceController.apply(bbn1) join_tree2 = InferenceController.apply(bbn2) posteriors1 = join_tree1.get_posteriors() posteriors2 = join_tree2.get_posteriors() for k, v1 in posteriors1.items(): assert k in posteriors2 v2 = posteriors2[k] assert len(v1) == len(v2) for k2 in v1: assert k2 in v2 diff = abs(v1[k2] - v2[k2]) assert diff < 0.01
def test_sampling(): """ Tests sampling a serial graph. :return: None. """ a = BbnNode(Variable(0, 'a', ['on', 'off']), [0.5, 0.5]) b = BbnNode(Variable(1, 'b', ['on', 'off']), [0.5, 0.5, 0.4, 0.6]) c = BbnNode(Variable(2, 'c', ['on', 'off']), [0.7, 0.3, 0.2, 0.8]) bbn = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) \ .add_edge(Edge(b, c, EdgeType.DIRECTED)) sampler = LogicSampler(bbn) n_samples = 10000 samples = pd.DataFrame(sampler.get_samples(n_samples=n_samples, seed=37)) samples.columns = ['a', 'b', 'c'] assert n_samples == samples.shape[0] assert 3 == samples.shape[1] s_a = samples.a.value_counts() s_b = samples.b.value_counts() s_c = samples.c.value_counts() s_a = s_a / s_a.sum() s_b = s_b / s_b.sum() s_c = s_c / s_c.sum() s_a = s_a.sort_index() s_b = s_b.sort_index() s_c = s_c.sort_index() assert_almost_equal(s_a.values, np.array([0.4985, 0.5015])) assert_almost_equal(s_b.values, np.array([0.5502, 0.4498])) assert_almost_equal(s_c.values, np.array([0.5721, 0.4279])) join_tree = InferenceController.apply(bbn) posteriors = join_tree.get_posteriors() assert_almost_equal(s_a.values, np.array( [posteriors['a']['off'], posteriors['a']['on']]), decimal=1) assert_almost_equal(s_b.values, np.array( [posteriors['b']['off'], posteriors['b']['on']]), decimal=1) assert_almost_equal(s_c.values, np.array( [posteriors['c']['off'], posteriors['c']['on']]), decimal=1)
def test_trivial_inference(): """ Tests inference on trivial graphs. :return: None. """ a1 = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b1 = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn1 = Bbn().add_node(a1).add_node(b1).add_edge( Edge(a1, b1, EdgeType.DIRECTED)) jt1 = InferenceController.apply(bbn1) a2 = BbnNode(Variable(1, 'a', ['t', 'f']), [0.2, 0.8]) b2 = BbnNode(Variable(0, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn2 = Bbn().add_node(a2).add_node(b2).add_edge( Edge(a2, b2, EdgeType.DIRECTED)) jt2 = InferenceController.apply(bbn2) a3 = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b3 = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9]) bbn3 = Bbn().add_node(a3).add_node(b3) jt3 = InferenceController.apply(bbn3) __validate_posterior__({ 'a': [0.2, 0.8], 'b': [0.74, 0.26] }, jt1, debug=False) __validate_posterior__({ 'a': [0.2, 0.8], 'b': [0.74, 0.26] }, jt2, debug=False) __validate_posterior__({ 'a': [0.2, 0.8], 'b': [0.1, 0.9] }, jt3, debug=False)
def test_reapply(): """ Tests reinitializing join tree after updating CPTs. :return: None. """ a = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn = Bbn().add_node(a).add_node(b) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) lhs = InferenceController.apply(bbn) rhs = InferenceController.reapply(lhs, { 0: [0.3, 0.7], 1: [0.2, 0.8, 0.8, 0.2] }) lhs_pot = [lhs.get_bbn_potential(n) for n in lhs.get_bbn_nodes()] rhs_pot = [rhs.get_bbn_potential(n) for n in rhs.get_bbn_nodes()] lhs_d = Potential.to_dict(lhs_pot) rhs_d = Potential.to_dict(rhs_pot) # lhs should not match rhs after CPT update for k, prob in lhs_d.items(): assert k in rhs_d assert prob != rhs_d[k] # now create lhs with same params as param used to update old # should match with rhs since params are now the same a = BbnNode(Variable(0, 'a', ['t', 'f']), [0.3, 0.7]) b = BbnNode(Variable(1, 'b', ['t', 'f']), [0.2, 0.8, 0.8, 0.2]) bbn = Bbn().add_node(a).add_node(b) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) lhs = InferenceController.apply(bbn) lhs_pot = [lhs.get_bbn_potential(n) for n in lhs.get_bbn_nodes()] lhs_d = Potential.to_dict(lhs_pot) for k, prob in lhs_d.items(): assert k in rhs_d assert_almost_equals(prob, rhs_d[k], 0.001)
def test_inference_var_permutation(): """ Tests inference on graphs where id are reversed. :return: None. """ a1 = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b1 = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) c1 = BbnNode(Variable(2, 'c', ['t', 'f']), [0.2, 0.8, 0.7, 0.3]) bbn1 = Bbn().add_node(a1).add_node(b1).add_node(c1) \ .add_edge(Edge(a1, b1, EdgeType.DIRECTED)) \ .add_edge(Edge(b1, c1, EdgeType.DIRECTED)) jt1 = InferenceController.apply(bbn1) a2 = BbnNode(Variable(2, 'a', ['t', 'f']), [0.2, 0.8]) b2 = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) c2 = BbnNode(Variable(0, 'c', ['t', 'f']), [0.2, 0.8, 0.7, 0.3]) bbn2 = Bbn().add_node(a2).add_node(b2).add_node(c2) \ .add_edge(Edge(a2, b2, EdgeType.DIRECTED)) \ .add_edge(Edge(b2, c2, EdgeType.DIRECTED)) jt2 = InferenceController.apply(bbn2) __validate_posterior__( { 'a': [0.2, 0.8], 'b': [0.74, 0.26], 'c': [0.33, 0.67] }, jt1, debug=False) __validate_posterior__( { 'a': [0.2, 0.8], 'b': [0.74, 0.26], 'c': [0.33, 0.67] }, jt2, debug=False)
def main(): # defining bbn variable to create a bayesian belief network global machine_name global join_tree # enter 1 or 2 as per your choice machine_type = int( input( "Choose : \n 1. Use Existing Machine \n 2. Configure a new machine \n\n" )) # if existing machine then ask for machine name and open it and process further if machine_type == 1: machine_name = str(input("Please input your machine name: ")) machine_name_file = '%s.sav' % machine_name try: join_tree = pickle.load(open(machine_name_file, 'rb')) for node in join_tree.get_bbn_nodes(): print(node) check(machine_name) potential_func() except: print("Machine name does not exists") main() else: machine_name = str(input("Please input your machine name: ")) globals()['machine_%s' % machine_name] = Bbn() # create the nodes create_bbn_nodes() # create the network structure by edges and nodes create_bbn_edges() join_tree = InferenceController.apply(globals()['machine_%s' % machine_name]) filename = '%s.sav' % machine_name pickle.dump(join_tree, open(filename, 'wb')) print(globals()['machine_%s' % machine_name]) check(machine_name) potential_func()
def test_inference_1(): """ Tests inference on the Huang graph with manual construction. :return: None. """ a = BbnNode(Variable(0, 'a', ['on', 'off']), [0.5, 0.5]) b = BbnNode(Variable(1, 'b', ['on', 'off']), [0.5, 0.5, 0.4, 0.6]) c = BbnNode(Variable(2, 'c', ['on', 'off']), [0.7, 0.3, 0.2, 0.8]) d = BbnNode(Variable(3, 'd', ['on', 'off']), [0.9, 0.1, 0.5, 0.5]) e = BbnNode(Variable(4, 'e', ['on', 'off']), [0.3, 0.7, 0.6, 0.4]) f = BbnNode(Variable(5, 'f', ['on', 'off']), [0.01, 0.99, 0.01, 0.99, 0.01, 0.99, 0.99, 0.01]) g = BbnNode(Variable(6, 'g', ['on', 'off']), [0.8, 0.2, 0.1, 0.9]) h = BbnNode(Variable(7, 'h', ['on', 'off']), [0.05, 0.95, 0.95, 0.05, 0.95, 0.05, 0.95, 0.05]) bbn = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_node(d) \ .add_node(e) \ .add_node(f) \ .add_node(g) \ .add_node(h) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) \ .add_edge(Edge(a, c, EdgeType.DIRECTED)) \ .add_edge(Edge(b, d, EdgeType.DIRECTED)) \ .add_edge(Edge(c, e, EdgeType.DIRECTED)) \ .add_edge(Edge(d, f, EdgeType.DIRECTED)) \ .add_edge(Edge(e, f, EdgeType.DIRECTED)) \ .add_edge(Edge(c, g, EdgeType.DIRECTED)) \ .add_edge(Edge(e, h, EdgeType.DIRECTED)) \ .add_edge(Edge(g, h, EdgeType.DIRECTED)) join_tree = InferenceController.apply(bbn) expected = { 'a': [0.5, 0.5], 'b': [0.45, 0.55], 'c': [0.45, 0.55], 'd': [0.680, 0.32], 'e': [0.465, 0.535], 'f': [0.176, 0.824], 'g': [0.415, 0.585], 'h': [0.823, 0.177] } __validate_posterior__(expected, join_tree)
def get_bbn(fpath): with open(fpath, 'r') as f: start = time.time() bbn = Bbn.from_dict(json.loads(f.read())) if fpath.endswith('.json') else Bbn.from_csv(fpath) stop = time.time() diff = stop - start print(f'{diff:.5f} : load time') start = time.time() jt = InferenceController.apply(bbn) stop = time.time() diff = stop - start print(f'{diff:.5f} : inference time') return bbn, jt
def test_github_issue_4(): """ Tests issue #4 https://github.com/vangj/py-bbn/issues/4 :return: None. """ a = BbnNode(Variable(0, 'A', ['T', 'F']), [0.5, 0.5]) b = BbnNode(Variable(1, 'B', ['T', 'F']), [0.2, 0.8, 0.1, 0.9]) c = BbnNode(Variable(2, 'C', ['T', 'F']), [0.5, 0.5, 0.5, 0.5]) d = BbnNode(Variable(3, 'D', ['T', 'F']), [0.5, 0.5, 0.5, 0.5]) e = BbnNode(Variable(4, 'E', ['T', 'F']), [0.5, 0.5, 0.5, 0.5]) f = BbnNode(Variable(5, 'F', ['T', 'F']), [0.5, 0.5, 0.5, 0.5]) g = BbnNode(Variable(6, 'G', ['T', 'F']), [ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ]) bbn = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_node(d) \ .add_node(e) \ .add_node(f) \ .add_node(g) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) \ .add_edge(Edge(a, c, EdgeType.DIRECTED)) \ .add_edge(Edge(b, d, EdgeType.DIRECTED)) \ .add_edge(Edge(b, e, EdgeType.DIRECTED)) \ .add_edge(Edge(c, f, EdgeType.DIRECTED)) \ .add_edge(Edge(e, g, EdgeType.DIRECTED)) \ .add_edge(Edge(d, g, EdgeType.DIRECTED)) \ .add_edge(Edge(f, g, EdgeType.DIRECTED)) join_tree = InferenceController.apply(bbn) expected = { 'A': [0.5, 0.5], 'B': [0.15, 0.85], 'C': [0.5, 0.5], 'D': [0.5, 0.5], 'E': [0.5, 0.5], 'F': [0.5, 0.5], 'G': [0.5, 0.5] } __validate_posterior__(expected, join_tree) __print_potentials__(join_tree)
def test_inference_controller(): bbn = BbnUtil.get_huang_graph() join_tree = InferenceController.apply(bbn) print('INIT') print_potentials(join_tree) ev = EvidenceBuilder()\ .with_node(join_tree.get_bbn_node(0))\ .with_evidence('on', 1.0)\ .build() join_tree.set_observation(ev) print('FIRST') print_potentials(join_tree)
def test_huang_inference_with_multiple_evidence(): """ Tests inference on the Huang graph with a multiple evidence. :return: None. """ bbn = BbnUtil.get_huang_graph() join_tree = InferenceController.apply(bbn) expected = { 'a': [0.5, 0.5], 'b': [0.45, 0.55], 'c': [0.45, 0.55], 'd': [0.68, 0.32], 'e': [0.465, 0.535], 'f': [0.176, 0.824], 'g': [0.415, 0.585], 'h': [0.823, 0.177] } __validate_posterior__(expected, join_tree) ev1 = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('a')) \ .with_evidence('on', 1.0) \ .build() ev2 = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('f')) \ .with_evidence('on', 1.0) \ .build() join_tree.unobserve_all() join_tree.update_evidences([ev1, ev2]) expected = { 'a': [1.0, 0.0], 'b': [0.184, 0.816], 'c': [0.798, 0.202], 'd': [0.0370, 0.963], 'e': [0.0206, 0.979], 'f': [1.0, 0.0], 'g': [0.658, 0.342], 'h': [0.941, 0.0588] } __validate_posterior__(expected, join_tree)
def test_from_libpgm_discrete_dictionary(): """ Tests create py-bbn BBN from dictionary specifying libpgm BBN. :return: None. """ d = get_dict() bbn = Factory.from_libpgm_discrete_dictionary(d) assert len(bbn.nodes) == 5 assert len(bbn.edges) == 4 # FIXME this is not working right somehow join_tree = InferenceController.apply(bbn) for node in join_tree.get_bbn_nodes(): potential = join_tree.get_bbn_potential(node) print(node) print(potential) print('>')
def test_inference_2(): """ Tests inference on customized graph. :return: None. """ a = BbnNode(Variable(0, 'a', ['on', 'off']), [0.7, 0.3]) b = BbnNode(Variable(1, 'b', ['on', 'off']), [0.4, 0.6]) c = BbnNode(Variable(2, 'c', ['on', 'off']), [0.9, 0.1, 0.3, 0.7, 0.5, 0.5, 0.1, 0.9]) d = BbnNode(Variable(3, 'd', ['on', 'off']), [0.3, 0.7, 0.8, 0.2]) e = BbnNode(Variable(4, 'e', ['on', 'off']), [0.6, 0.4, 0.2, 0.8]) f = BbnNode(Variable(5, 'f', ['on', 'off']), [0.7, 0.3, 0.1, 0.9]) g = BbnNode(Variable(6, 'g', ['on', 'off']), [0.4, 0.6, 0.9, 0.1]) bbn = Bbn() \ .add_node(a) \ .add_node(b) \ .add_node(c) \ .add_node(d) \ .add_node(e) \ .add_node(f) \ .add_node(g) \ .add_edge(Edge(a, c, EdgeType.DIRECTED)) \ .add_edge(Edge(b, c, EdgeType.DIRECTED)) \ .add_edge(Edge(c, d, EdgeType.DIRECTED)) \ .add_edge(Edge(c, e, EdgeType.DIRECTED)) \ .add_edge(Edge(d, f, EdgeType.DIRECTED)) \ .add_edge(Edge(d, g, EdgeType.DIRECTED)) join_tree = InferenceController.apply(bbn) expected = { 'a': [0.7, 0.3], 'b': [0.4, 0.6], 'c': [0.456, 0.544], 'd': [0.572, 0.428], 'e': [0.382, 0.618], 'f': [0.443, 0.557], 'g': [0.614, 0.386] } __validate_posterior__(expected, join_tree)
def test_from_libpgm_discrete_dictionary(): """ Tests create py-bbn BBN from dictionary specifying libpgm BBN. :return: None. """ d = get_dict() bbn = Factory.from_libpgm_discrete_dictionary(d) assert len(bbn.nodes) == 5 assert len(bbn.edges) == 4 join_tree = InferenceController.apply(bbn) __validate_posterior__({ 'Difficulty': [0.6, 0.4], 'Intelligence': [0.7, 0.3], 'Grade': [0.362, 0.288, 0.350], 'SAT': [0.725, 0.275], 'Letter': [0.498, 0.502] }, join_tree, debug=True)
def test_huang_inference_with_single_evidence(): """ Tests inference on the Huang graph with a single evidence. :return: None. """ bbn = BbnUtil.get_huang_graph() join_tree = InferenceController.apply(bbn) expected = { 'a': [0.5, 0.5], 'b': [0.45, 0.55], 'c': [0.45, 0.55], 'd': [0.68, 0.32], 'e': [0.465, 0.535], 'f': [0.176, 0.824], 'g': [0.415, 0.585], 'h': [0.823, 0.177] } __validate_posterior__(expected, join_tree) ev = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('a')) \ .with_evidence('on', 1.0) \ .build() join_tree.unobserve_all() join_tree.set_observation(ev) expected = { 'a': [1.0, 0.0], 'b': [0.5, 0.5], 'c': [0.7, 0.3], 'd': [0.7, 0.3], 'e': [0.39, 0.61], 'f': [0.18934, 0.81066], 'g': [0.59, 0.41], 'h': [0.7826, 0.2174] } __validate_posterior__(expected, join_tree)
def test_simple_inference(): """ Tests inference on the Huang graph. :return: None. """ bbn = BbnUtil.get_simple() join_tree = InferenceController.apply(bbn) expected = { 'a': [0.5, 0.5], 'b': [0.45, 0.55], 'c': [0.45, 0.55], 'd': [0.68, 0.32], 'e': [0.465, 0.535], 'f': [0.176, 0.824] } __validate_posterior__(expected, join_tree) __print_potentials__(join_tree)
def test_inference_libpgm2(): """ Tests libpgm graph where ordering messes up computation. :return: None. """ letter = BbnNode(Variable(4, 'Letter', ['weak', 'strong']), [0.1, 0.9, 0.4, 0.6, 0.99, 0.01]) grade = BbnNode( Variable(2, 'Grade', ['a', 'b', 'c']), [0.3, 0.4, 0.3, 0.9, 0.08, 0.02, 0.05, 0.25, 0.7, 0.5, 0.3, 0.2]) intelligence = BbnNode(Variable(3, 'Intelligence', ['low', 'high']), [0.7, 0.3]) sat = BbnNode(Variable(1, 'SAT', ['low', 'high']), [0.95, 0.05, 0.2, 0.8]) difficulty = BbnNode(Variable(0, 'Difficulty', ['easy', 'hard']), [0.6, 0.4]) bbn = Bbn() \ .add_node(letter) \ .add_node(grade) \ .add_node(intelligence) \ .add_node(sat) \ .add_node(difficulty) \ .add_edge(Edge(difficulty, grade, EdgeType.DIRECTED)) \ .add_edge(Edge(intelligence, grade, EdgeType.DIRECTED)) \ .add_edge(Edge(intelligence, sat, EdgeType.DIRECTED)) \ .add_edge(Edge(grade, letter, EdgeType.DIRECTED)) join_tree = InferenceController.apply(bbn) __validate_posterior__( { 'Difficulty': [0.6, 0.4], 'Intelligence': [0.7, 0.3], 'Grade': [0.362, 0.288, 0.350], 'SAT': [0.725, 0.275], 'Letter': [0.498, 0.502] }, join_tree, debug=False)
def test_simple_serde(): """ Tests join tree serde with only 1 clique. :return: None. """ a = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn = Bbn().add_node(a).add_node(b) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) lhs = InferenceController.apply(bbn) d = JoinTree.to_dict(lhs) rhs = JoinTree.from_dict(d) rhs = InferenceController.apply_from_serde(rhs) lhs_pot = [lhs.get_bbn_potential(n) for n in lhs.get_bbn_nodes()] rhs_pot = [rhs.get_bbn_potential(n) for n in rhs.get_bbn_nodes()] lhs_pot = Potential.to_dict(lhs_pot) rhs_pot = Potential.to_dict(rhs_pot) assert len(lhs_pot) == len(rhs_pot)
def test_forest_inference(): """ Tests inference on a disconnected DAG; sub-DAGs are a -> b, c -> d and e -> f. :return: None. """ a = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) c = BbnNode(Variable(2, 'c', ['t', 'f']), [0.2, 0.8]) d = BbnNode(Variable(3, 'd', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) e = BbnNode(Variable(4, 'e', ['t', 'f']), [0.2, 0.8]) f = BbnNode(Variable(5, 'f', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn = Bbn().add_node(a).add_node(b).add_node(c).add_node(d).add_node(e).add_node(f) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) \ .add_edge(Edge(c, d, EdgeType.DIRECTED)) \ .add_edge(Edge(e, f, EdgeType.DIRECTED)) jt = InferenceController.apply(bbn) pot = [jt.get_bbn_potential(n) for n in jt.get_bbn_nodes()] o = Potential.to_dict(pot) e = { '0=t': 0.2, '0=f': 0.8, '1=t': 0.7400000000000001, '1=f': 0.26, '2=t': 0.2, '2=f': 0.8, '3=t': 0.7400000000000001, '3=f': 0.26, '4=t': 0.2, '4=f': 0.8, '5=t': 0.7400000000000001, '5=f': 0.26 } for k, p in e.items(): assert_almost_equals(p, o[k], 0.001)
def do_it(bbn): InferenceController.apply(bbn)
.add_edge(Edge(ap, sir, EdgeType.DIRECTED)) \ .add_edge(Edge(p, sir, EdgeType.DIRECTED)) \ .add_edge(Edge(sir, wbc, EdgeType.DIRECTED)) options = { "font_size": 16, "node_size": 3000, "node_color": "white", "edgecolors": "black", "edge_color": "red", "linewidths": 5, "width": 5, } n, d = bbn.to_nx_graph() nx.draw(n, with_labels=True, labels=d, **options) join_tree = InferenceController.apply(bbn) ev = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('ap')) \ .with_evidence('yes', 1) \ .build() ev2 = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('p')) \ .with_evidence('yes', 1) \ .build() ev3 = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('wbc')) \ .with_evidence('high', 1) \ .build()
def test_inference_libpgm(): """ Tests inference with evidence on libpgm graph. :return: None. """ difficulty = BbnNode(Variable(0, 'difficulty', ['easy', 'hard']), [0.6, 0.4]) intelligence = BbnNode(Variable(1, 'intelligence', ['low', 'high']), [0.7, 0.3]) grade = BbnNode( Variable(2, 'grade', ['a', 'b', 'c']), [0.3, 0.4, 0.3, 0.9, 0.08, 0.02, 0.05, 0.25, 0.7, 0.5, 0.3, 0.2]) sat = BbnNode(Variable(3, 'sat', ['low', 'high']), [0.95, 0.05, 0.2, 0.8]) letter = BbnNode(Variable(4, 'letter', ['weak', 'strong']), [0.1, 0.9, 0.4, 0.6, 0.99, 0.01]) bbn = Bbn() \ .add_node(difficulty) \ .add_node(intelligence) \ .add_node(grade) \ .add_node(sat) \ .add_node(letter) \ .add_edge(Edge(difficulty, grade, EdgeType.DIRECTED)) \ .add_edge(Edge(intelligence, grade, EdgeType.DIRECTED)) \ .add_edge(Edge(intelligence, sat, EdgeType.DIRECTED)) \ .add_edge(Edge(grade, letter, EdgeType.DIRECTED)) join_tree = InferenceController.apply(bbn) __validate_posterior__( { 'difficulty': [0.6, 0.4], 'intelligence': [0.7, 0.3], 'grade': [0.362, 0.288, 0.350], 'sat': [0.725, 0.275], 'letter': [0.498, 0.502] }, join_tree) ev = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('sat')) \ .with_evidence('high', 1.0) \ .build() join_tree.unobserve_all() join_tree.set_observation(ev) __validate_posterior__( { 'difficulty': [0.6, 0.4], 'intelligence': [0.127, 0.873], 'grade': [0.671, 0.190, 0.139], 'sat': [0.0, 1.0], 'letter': [0.281, 0.719] }, join_tree) ev = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('sat')) \ .with_evidence('low', 1.0) \ .build() join_tree.unobserve_all() join_tree.set_observation(ev) __validate_posterior__( { 'difficulty': [0.6, 0.4], 'intelligence': [0.917, 0.0828], 'grade': [0.245, 0.326, 0.430], 'sat': [1.0, 0.0], 'letter': [0.58, 0.42] }, join_tree)
def bayesian_belief_network(): deadline = BbnNode(Variable(0, 'deadline', ['long', 'medium', 'short']), [0.33, 0.33, 0.33]) goal = BbnNode(Variable(1, 'goal', ['large', 'medium', 'small']), [0.33, 0.33, 0.33]) backers = BbnNode(Variable(3, 'backers', ['many', 'medium', 'few']), [0.6, 0.3, 0.2, 0.3, 0.4, 0.4, 0.1, 0.3, 0.4]) pledges = BbnNode(Variable(4, 'pledges', ['large', 'medium', 'small']), [0.6, 0.3, 0.1, 0.2, 0.5, 0.2, 0.2, 0.2, 0.7]) state = BbnNode(Variable(5, 'state', ['success', 'fail']), [ 0.7, 0.5, 0.2, 0.8, 0.6, 0.2, 0.9, 0.7, 0.3, 0.3, 0.5, 0.8, 0.2, 0.4, 0.8, 0.1, 0.3, 0.7 ]) global Bbn Bbn = Bbn() \ .add_node(deadline) \ .add_node(goal) \ .add_node(backers) \ .add_node(pledges) \ .add_node(state) \ .add_edge(Edge( goal, backers, EdgeType.DIRECTED)) \ .add_edge(Edge( goal, pledges, EdgeType.DIRECTED)) \ .add_edge(Edge( backers, state, EdgeType.DIRECTED)) \ .add_edge(Edge( deadline, state, EdgeType.DIRECTED)) with warnings.catch_warnings(): warnings.simplefilter('ignore') graph = convert_for_drawing(Bbn) pos = nx.nx_agraph.graphviz_layout(graph, prog='dot') #uncomment this section to print BBN #plt.figure(figsize=(8, 8)) #plt.subplot(121) #labels = dict([(k, node.variable.name) for k, node in Bbn.nodes.items()]) #nx.draw(graph, pos=pos, with_labels=True, labels=labels) #plt.title('Bayesian Belief Network Diagram') #plt.show() join_tree = InferenceController.apply(Bbn) print("BBN - Original Probabilities") for node in join_tree.get_bbn_nodes(): potential = join_tree.get_bbn_potential(node) print(node) print(potential) print('--------------------->') # insert an observation evidence ev = EvidenceBuilder() \ .with_node(join_tree.get_bbn_node_by_name('goal')) \ .with_evidence('large', 1.0) \ .build() join_tree.set_observation(ev) #print the marginal probabilities print() print() print("BBN - Set Goal = Large") for node in join_tree.get_bbn_nodes(): potential = join_tree.get_bbn_potential(node) print(node) print(potential) print('--------------------->')
def test_to_dict(): """ Tests serializing join tree to dictionary. :return: None. """ n0 = BbnNode(Variable(0, 'n0', ['t', 'f']), [0.2, 0.8]) n1 = BbnNode(Variable(1, 'n1', ['t', 'f']), [0.9, 0.1, 0.9, 0.1]) n2 = BbnNode(Variable(2, 'n2', ['t', 'f']), [0.6, 0.4, 0.4, 0.6]) bbn = Bbn().add_node(n0).add_node(n1).add_node(n2) \ .add_edge(Edge(n0, n1, EdgeType.DIRECTED)) \ .add_edge(Edge(n1, n2, EdgeType.DIRECTED)) jt = InferenceController.apply(bbn) d = JoinTree.to_dict(jt) lhs = json.dumps(d, sort_keys=True, indent=2) rhs = """{ "bbn_nodes": { "0": { "probs": [ 0.2, 0.8 ], "variable": { "id": 0, "name": "n0", "values": [ "t", "f" ] } }, "1": { "probs": [ 0.9, 0.1, 0.9, 0.1 ], "variable": { "id": 1, "name": "n1", "values": [ "t", "f" ] } }, "2": { "probs": [ 0.6, 0.4, 0.4, 0.6 ], "variable": { "id": 2, "name": "n2", "values": [ "t", "f" ] } } }, "jt": { "edges": [ "0-1-1-1-2" ], "nodes": { "0-1": { "node_ids": [ 0, 1 ], "type": "clique" }, "0-1-1-1-2": { "left": "0-1", "right": "1-2", "type": "sepset" }, "1-2": { "node_ids": [ 1, 2 ], "type": "clique" } }, "parent_info": { "0": [], "1": [ 0 ], "2": [ 1 ] } } }""" assert lhs == rhs
def test_from_dict(): """ Tests deserializing from dictionary. :return: """ s = """{ "bbn_nodes": { "0": { "probs": [ 0.2, 0.8 ], "variable": { "id": 0, "name": "n0", "values": [ "t", "f" ] } }, "1": { "probs": [ 0.9, 0.1, 0.9, 0.1 ], "variable": { "id": 1, "name": "n1", "values": [ "t", "f" ] } }, "2": { "probs": [ 0.6, 0.4, 0.4, 0.6 ], "variable": { "id": 2, "name": "n2", "values": [ "t", "f" ] } } }, "jt": { "edges": [ "0-1-1-1-2" ], "nodes": { "0-1": { "node_ids": [ 0, 1 ], "type": "clique" }, "0-1-1-1-2": { "left": "0-1", "right": "1-2", "type": "sepset" }, "1-2": { "node_ids": [ 1, 2 ], "type": "clique" } }, "parent_info": { "0": [], "1": [ 0 ], "2": [ 1 ] } } }""" d = json.loads(s) lhs = JoinTree.from_dict(d) lhs = InferenceController.apply_from_serde(lhs) n0 = BbnNode(Variable(0, 'n0', ['t', 'f']), [0.2, 0.8]) n1 = BbnNode(Variable(1, 'n1', ['t', 'f']), [0.9, 0.1, 0.9, 0.1]) n2 = BbnNode(Variable(2, 'n2', ['t', 'f']), [0.6, 0.4, 0.4, 0.6]) bbn = Bbn().add_node(n0).add_node(n1).add_node(n2) \ .add_edge(Edge(n0, n1, EdgeType.DIRECTED)) \ .add_edge(Edge(n1, n2, EdgeType.DIRECTED)) rhs = InferenceController.apply(bbn) lhs_pot = [lhs.get_bbn_potential(n) for n in lhs.get_bbn_nodes()] rhs_pot = [rhs.get_bbn_potential(n) for n in rhs.get_bbn_nodes()] lhs_pot = Potential.to_dict(lhs_pot) rhs_pot = Potential.to_dict(rhs_pot) assert len(lhs_pot) == len(rhs_pot) for k, p in lhs_pot.items(): assert_almost_equals(p, rhs_pot[k], 0.001)
import json from pybbn.graph.dag import Bbn from pybbn.graph.edge import EdgeType, Edge from pybbn.graph.jointree import JoinTree from pybbn.graph.node import BbnNode from pybbn.graph.variable import Variable from pybbn.pptc.inferencecontroller import InferenceController a = BbnNode(Variable(0, 'a', ['t', 'f']), [0.2, 0.8]) b = BbnNode(Variable(1, 'b', ['t', 'f']), [0.1, 0.9, 0.9, 0.1]) bbn = Bbn().add_node(a).add_node(b) \ .add_edge(Edge(a, b, EdgeType.DIRECTED)) jt = InferenceController.apply(bbn) with open('simple-join-tree.json', 'w') as f: d = JoinTree.to_dict(jt) j = json.dumps(d, sort_keys=True, indent=2) f.write(j)