def setUp(self): """""" # Koller, Friedman 2009, p. 104 self.Bf = NumCatRVariable( node_id="B", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Cf = NumCatRVariable( node_id="C", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) def phibc(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 0.5 elif sfs == set([("B", 10), ("C", 50)]): return 0.7 elif sfs == set([("B", 50), ("C", 10)]): return 0.1 elif sfs == set([("B", 50), ("C", 50)]): return 0.2 else: raise ValueError("unknown arg") self.bc = Factor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc) self.bc_b = BaseFactor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc)
def test_from_scope_variables_with_fn(self): """""" A = NumCatRVariable( "A", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.6 if x else 0.4, ) B = NumCatRVariable( "B", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.62 if x else 0.38, ) def phi_ab(scope_product): ss = set(scope_product) if ss == set([("A", True), ("B", True)]): return 0.9 elif ss == set([("A", True), ("B", False)]): return 0.1 elif ss == set([("A", False), ("B", True)]): return 0.2 elif ss == set([("A", False), ("B", False)]): return 0.8 else: raise ValueError("unknown argument") f = Factor.from_scope_variables_with_fn(svars=set([A, B]), fn=phi_ab) query = set([("A", True), ("B", True)]) ff = f.phi(query) self.assertEqual(round(ff, 2), 0.9)
def data_2(self): """""" # Koller, Friedman 2009, p. 104 self.Af = NumCatRVariable( node_id="A", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Bf = NumCatRVariable( node_id="B", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Cf = NumCatRVariable( node_id="C", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Df = NumCatRVariable( node_id="D", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) def phiAB(scope_product): """""" sfs = set(scope_product) if sfs == set([("A", 10), ("B", 10)]): return 30 elif sfs == set([("A", 10), ("B", 50)]): return 5 elif sfs == set([("A", 50), ("B", 10)]): return 1 elif sfs == set([("A", 50), ("B", 50)]): return 10 else: raise ValueError("unknown arg") self.AB = Factor(gid="AB", scope_vars=set([self.Af, self.Bf]), factor_fn=phiAB) def phiBC(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 100 elif sfs == set([("B", 10), ("C", 50)]): return 1 elif sfs == set([("B", 50), ("C", 10)]): return 1 elif sfs == set([("B", 50), ("C", 50)]): return 100 else: raise ValueError("unknown arg") self.BC = Factor(gid="BC", scope_vars=set([self.Bf, self.Cf]), factor_fn=phiBC)
def setUp(self): """""" self.data_1() self.data_2() # Koller, Friedman 2009 p. 107 self.af = NumCatRVariable( node_id="A", input_data={"outcome-values": [10, 50, 20]}, marginal_distribution=lambda x: 0.4 if x != 20 else 0.2, ) def phiaB(scope_product): """""" sfs = set(scope_product) if sfs == set([("A", 10), ("B", 10)]): return 0.5 elif sfs == set([("A", 10), ("B", 50)]): return 0.8 elif sfs == set([("A", 50), ("B", 10)]): return 0.1 elif sfs == set([("A", 50), ("B", 50)]): return 0 elif sfs == set([("A", 20), ("B", 10)]): return 0.3 elif sfs == set([("A", 20), ("B", 50)]): return 0.9 else: raise ValueError("unknown arg") self.aB = Factor(gid="ab", scope_vars=set([self.af, self.Bf]), factor_fn=phiaB) self.aB_b = BaseFactor(gid="ab", scope_vars=set([self.af, self.Bf]), factor_fn=phiaB) def phibc(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 0.5 elif sfs == set([("B", 10), ("C", 50)]): return 0.7 elif sfs == set([("B", 50), ("C", 10)]): return 0.1 elif sfs == set([("B", 50), ("C", 50)]): return 0.2 else: raise ValueError("unknown arg") self.bc = Factor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc) self.bc_b = BaseFactor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc)
def data_1(self): """""" idata = {"outcome-values": [True, False]} self.A = NumCatRVariable(node_id="A", input_data=idata, marginal_distribution=lambda x: 0.5) self.B = NumCatRVariable(node_id="B", input_data=idata, marginal_distribution=lambda x: 0.5) self.C = NumCatRVariable(node_id="C", input_data=idata, marginal_distribution=lambda x: 0.5) self.D = NumCatRVariable(node_id="D", input_data=idata, marginal_distribution=lambda x: 0.5) self.E = NumCatRVariable(node_id="E", input_data=idata, marginal_distribution=lambda x: 0.5) self.F = NumCatRVariable(node_id="F", input_data=idata, marginal_distribution=lambda x: 0.5) self.G = NumCatRVariable(node_id="G", input_data=idata, marginal_distribution=lambda x: 0.5) self.H = NumCatRVariable(node_id="H", input_data=idata, marginal_distribution=lambda x: 0.5) self.Irvar = NumCatRVariable(node_id="I", input_data=idata, marginal_distribution=lambda x: 0.5) self.K = NumCatRVariable(node_id="K", input_data=idata, marginal_distribution=lambda x: 0.5) self.L = NumCatRVariable(node_id="L", input_data=idata, marginal_distribution=lambda x: 0.5) # # Cowell 2005, p. 110 # # A E---+ # | | # +----+ F <-+ # | | # B <--+---> C --> D <---+ # | | # +---> H <--------+----> G # | | # +---> I # self.AB_c = Edge( edge_id="AB", start_node=self.A, end_node=self.B, edge_type=EdgeType.DIRECTED, ) self.AC_c = Edge( edge_id="AC", start_node=self.A, end_node=self.C, edge_type=EdgeType.DIRECTED, ) self.CD_c = Edge( edge_id="CD", start_node=self.C, end_node=self.D, edge_type=EdgeType.DIRECTED, ) self.EF_c = Edge( edge_id="EF", start_node=self.E, end_node=self.F, edge_type=EdgeType.DIRECTED, ) self.FD_c = Edge( edge_id="FD", start_node=self.F, end_node=self.D, edge_type=EdgeType.DIRECTED, ) self.DG_c = Edge( edge_id="DG", start_node=self.D, end_node=self.G, edge_type=EdgeType.DIRECTED, ) self.DH_c = Edge( edge_id="DH", start_node=self.D, end_node=self.H, edge_type=EdgeType.DIRECTED, ) self.BH_c = Edge( edge_id="BH", start_node=self.B, end_node=self.H, edge_type=EdgeType.DIRECTED, ) self.BI_c = Edge( edge_id="BI", start_node=self.B, end_node=self.Irvar, edge_type=EdgeType.DIRECTED, ) self.HI_c = Edge( edge_id="HI", start_node=self.H, end_node=self.Irvar, edge_type=EdgeType.UNDIRECTED, )
class LWFChainGraphTest(unittest.TestCase): """""" def data_1(self): """""" idata = {"outcome-values": [True, False]} self.A = NumCatRVariable(node_id="A", input_data=idata, marginal_distribution=lambda x: 0.5) self.B = NumCatRVariable(node_id="B", input_data=idata, marginal_distribution=lambda x: 0.5) self.C = NumCatRVariable(node_id="C", input_data=idata, marginal_distribution=lambda x: 0.5) self.D = NumCatRVariable(node_id="D", input_data=idata, marginal_distribution=lambda x: 0.5) self.E = NumCatRVariable(node_id="E", input_data=idata, marginal_distribution=lambda x: 0.5) self.F = NumCatRVariable(node_id="F", input_data=idata, marginal_distribution=lambda x: 0.5) self.G = NumCatRVariable(node_id="G", input_data=idata, marginal_distribution=lambda x: 0.5) self.H = NumCatRVariable(node_id="H", input_data=idata, marginal_distribution=lambda x: 0.5) self.Irvar = NumCatRVariable(node_id="I", input_data=idata, marginal_distribution=lambda x: 0.5) self.K = NumCatRVariable(node_id="K", input_data=idata, marginal_distribution=lambda x: 0.5) self.L = NumCatRVariable(node_id="L", input_data=idata, marginal_distribution=lambda x: 0.5) # # Cowell 2005, p. 110 # # A E---+ # | | # +----+ F <-+ # | | # B <--+---> C --> D <---+ # | | # +---> H <--------+----> G # | | # +---> I # self.AB_c = Edge( edge_id="AB", start_node=self.A, end_node=self.B, edge_type=EdgeType.DIRECTED, ) self.AC_c = Edge( edge_id="AC", start_node=self.A, end_node=self.C, edge_type=EdgeType.DIRECTED, ) self.CD_c = Edge( edge_id="CD", start_node=self.C, end_node=self.D, edge_type=EdgeType.DIRECTED, ) self.EF_c = Edge( edge_id="EF", start_node=self.E, end_node=self.F, edge_type=EdgeType.DIRECTED, ) self.FD_c = Edge( edge_id="FD", start_node=self.F, end_node=self.D, edge_type=EdgeType.DIRECTED, ) self.DG_c = Edge( edge_id="DG", start_node=self.D, end_node=self.G, edge_type=EdgeType.DIRECTED, ) self.DH_c = Edge( edge_id="DH", start_node=self.D, end_node=self.H, edge_type=EdgeType.DIRECTED, ) self.BH_c = Edge( edge_id="BH", start_node=self.B, end_node=self.H, edge_type=EdgeType.DIRECTED, ) self.BI_c = Edge( edge_id="BI", start_node=self.B, end_node=self.Irvar, edge_type=EdgeType.DIRECTED, ) self.HI_c = Edge( edge_id="HI", start_node=self.H, end_node=self.Irvar, edge_type=EdgeType.UNDIRECTED, ) def data_2(self): """""" def phi_e(scope_product): """! Visit to Asia factor p(a) """ ss = set(scope_product) if ss == set([("E", True)]): return 0.01 elif ss == set([("E", False)]): return 0.99 else: raise ValueError("Unknown scope product") self.E_cf = Factor(gid="E_cf", scope_vars=set([self.E]), factor_fn=phi_e) def phi_fe(scope_product): """! Tuberculosis | Visit to Asia factor p(t,a) """ ss = set(scope_product) if ss == set([("F", True), ("E", True)]): return 0.05 elif ss == set([("F", False), ("E", True)]): return 0.95 elif ss == set([("F", True), ("E", False)]): return 0.01 elif ss == set([("F", False), ("E", False)]): return 0.99 else: raise ValueError("Unknown scope product") self.EF_cf = Factor(gid="EF_cf", scope_vars=set([self.E, self.F]), factor_fn=phi_fe) def phi_dg(scope_product): """! either tuberculosis or lung cancer | x ray p(e,x) """ ss = set(scope_product) if ss == set([("D", True), ("G", True)]): return 0.98 elif ss == set([("D", False), ("G", True)]): return 0.05 elif ss == set([("D", True), ("G", False)]): return 0.02 elif ss == set([("D", False), ("G", False)]): return 0.95 else: raise ValueError("Unknown scope product") self.DG_cf = Factor(gid="DG_cf", scope_vars=set([self.D, self.G]), factor_fn=phi_dg) def data_3(self): """""" def phi_a(scope_product): """! smoke factor p(s) """ ss = set(scope_product) if ss == set([("A", True)]): return 0.5 elif ss == set([("A", False)]): return 0.5 else: raise ValueError("Unknown scope product") self.A_cf = Factor(gid="A_cf", scope_vars=set([self.A]), factor_fn=phi_a) def phi_ab(scope_product): """! smoke given bronchitis p(s,b) """ ss = set(scope_product) if ss == set([("A", True), ("B", True)]): return 0.6 elif ss == set([("A", False), ("B", True)]): return 0.3 elif ss == set([("A", True), ("B", False)]): return 0.4 elif ss == set([("A", False), ("B", False)]): return 0.7 else: raise ValueError("Unknown scope product") self.AB_cf = Factor(gid="AB_cf", scope_vars=set([self.A, self.B]), factor_fn=phi_ab) def phi_ac(scope_product): """! lung cancer given smoke p(s,l) """ ss = set(scope_product) if ss == set([("A", True), ("C", True)]): return 0.1 elif ss == set([("A", False), ("C", True)]): return 0.01 elif ss == set([("A", True), ("C", False)]): return 0.9 elif ss == set([("A", False), ("C", False)]): return 0.99 else: raise ValueError("Unknown scope product") self.AC_cf = Factor(gid="AC_cf", scope_vars=set([self.A, self.C]), factor_fn=phi_ac) def data_4(self): """""" # Factors # def phi_cdf(scope_product): """! either tuberculosis or lung given lung cancer and tuberculosis p(e, l, t) """ ss = set(scope_product) if ss == set([("C", True), ("D", True), ("F", True)]): return 1 elif ss == set([("C", True), ("D", False), ("F", True)]): return 0 elif ss == set([("C", False), ("D", True), ("F", True)]): return 1 elif ss == set([("C", False), ("D", False), ("F", True)]): return 0 elif ss == set([("C", True), ("D", True), ("F", False)]): return 1 elif ss == set([("C", True), ("D", False), ("F", False)]): return 0 elif ss == set([("C", False), ("D", True), ("F", False)]): return 0 elif ss == set([("C", False), ("D", False), ("F", False)]): return 1 else: raise ValueError("Unknown scope product") self.CDF_cf = Factor( gid="CDF_cf", scope_vars=set([self.D, self.C, self.F]), factor_fn=phi_cdf, ) def phi_ihb(scope_product): """! cough, dyspnoea, bronchitis I, H, B p(c,d,b) """ ss = set(scope_product) if ss == set([("H", True), ("I", True), ("B", True)]): return 16 elif ss == set([("H", True), ("I", False), ("B", True)]): return 1 elif ss == set([("H", False), ("I", True), ("B", True)]): return 4 elif ss == set([("H", False), ("I", False), ("B", True)]): return 1 elif ss == set([("H", True), ("I", True), ("B", False)]): return 2 elif ss == set([("H", True), ("I", False), ("B", False)]): return 1 elif ss == set([("H", False), ("I", True), ("B", False)]): return 1 elif ss == set([("H", False), ("I", False), ("B", False)]): return 1 else: raise ValueError("Unknown scope product") self.IHB_cf = Factor( gid="IHB_cf", scope_vars=set([self.H, self.Irvar, self.B]), factor_fn=phi_ihb, ) def phi_hbd(scope_product): """! cough, either tuberculosis or lung cancer, bronchitis D, H, B p(c,b,e) """ ss = set(scope_product) if ss == set([("H", True), ("D", True), ("B", True)]): return 5 elif ss == set([("H", True), ("D", False), ("B", True)]): return 2 elif ss == set([("H", False), ("D", True), ("B", True)]): return 1 elif ss == set([("H", False), ("D", False), ("B", True)]): return 1 elif ss == set([("H", True), ("D", True), ("B", False)]): return 3 elif ss == set([("H", True), ("D", False), ("B", False)]): return 1 elif ss == set([("H", False), ("D", True), ("B", False)]): return 1 elif ss == set([("H", False), ("D", False), ("B", False)]): return 1 else: raise ValueError("Unknown scope product") self.HBD_cf = Factor( gid="HBD_cf", scope_vars=set([self.H, self.D, self.B]), factor_fn=phi_hbd, ) def phi_bd(scope_product): """! bronchitis, either tuberculosis or lung cancer B, D p(b,e) """ ss = set(scope_product) if ss == set([("B", True), ("D", True)]): return 1 / 90 elif ss == set([("B", False), ("D", True)]): return 1 / 11 elif ss == set([("B", True), ("D", False)]): return 1 / 39 elif ss == set([("B", False), ("D", False)]): return 1 / 5 else: raise ValueError("Unknown scope product") self.BD_cf = Factor(gid="BD_cf", scope_vars=set([self.D, self.B]), factor_fn=phi_bd) def setUp(self): """""" self.data_1() self.data_2() self.data_3() self.data_4() # self.cowell = LWFChainGraph( gid="cowell", nodes=set([ self.A, self.B, self.C, self.D, self.E, self.F, self.G, self.H, self.Irvar, ]), edges=set([ self.AB_c, self.AC_c, self.CD_c, self.EF_c, self.FD_c, self.DG_c, self.DH_c, self.BH_c, self.BI_c, self.HI_c, ]), factors=set([ self.E_cf, self.EF_cf, self.DG_cf, self.A_cf, self.AB_cf, self.AC_cf, self.CDF_cf, self.IHB_cf, self.HBD_cf, self.BD_cf, ]), ) # Koller, Friedman 2009, p. 149 # # +--------------+ # | | # | A + B # | | | | # | +--> C -- D -- E <--+ # | | | | # | +--+ | v # | | +-------> I <---- H # | F <-+ # | | # | +----- G # | ^ # | | # +----------+ self.AC_k = Edge( edge_id="AC", start_node=self.A, end_node=self.C, edge_type=EdgeType.DIRECTED, ) self.FG_k = Edge( edge_id="FG", start_node=self.F, end_node=self.G, edge_type=EdgeType.UNDIRECTED, ) self.DG_k = Edge( edge_id="DG", start_node=self.D, end_node=self.G, edge_type=EdgeType.DIRECTED, ) self.CF_k = Edge( edge_id="CF", start_node=self.C, end_node=self.F, edge_type=EdgeType.UNDIRECTED, ) self.CD_k = Edge( edge_id="CD", start_node=self.C, end_node=self.D, edge_type=EdgeType.UNDIRECTED, ) self.CI_k = Edge( edge_id="CI", start_node=self.C, end_node=self.Irvar, edge_type=EdgeType.DIRECTED, ) self.DE_k = Edge( edge_id="DE", start_node=self.D, end_node=self.E, edge_type=EdgeType.UNDIRECTED, ) self.EI_k = Edge( edge_id="EI", start_node=self.E, end_node=self.Irvar, edge_type=EdgeType.DIRECTED, ) self.BE_k = Edge( edge_id="BE", start_node=self.B, end_node=self.E, edge_type=EdgeType.DIRECTED, ) self.HI_k = Edge( edge_id="HI", start_node=self.H, end_node=self.Irvar, edge_type=EdgeType.DIRECTED, ) self.koller = LWFChainGraph( gid="koller", nodes=set([ self.A, self.C, self.D, self.E, self.B, self.Irvar, self.F, self.G, ]), edges=set([ self.AC_k, self.FG_k, self.CF_k, self.HI_k, self.CD_k, self.CI_k, self.DE_k, self.DG_k, self.EI_k, self.BE_k, ]), factors=None, ) # evidence values taken from # Cowell 2005, p. 119, table 6.12 e_comp_val = [("E", True, 0.0096), ("E", False, 0.9904)] h_comp_val = [("H", True, 0.7635), ("H", False, 0.2365)] c_comp_val = [("C", True, 0.0025), ("C", False, 0.9975)] i_comp_val = [("I", True, 0.7939), ("I", False, 0.2061)] g_comp_val = [("G", True, 0.1849), ("G", False, 0.8151)] a_comp_val = [("A", True, 0.4767), ("A", False, 0.5233)] f_comp_val = [("F", True, 0.0012), ("F", False, 0.9988)] d_comp_val = [("D", True, 0.0036), ("D", False, 0.9964)] b_comp_val = [("B", True, 0.60), ("B", False, 0.40)] self.evidences = set([("E", True), ("A", True), ("G", False)]) self.q_tsts = { (self.E): e_comp_val, # asia (self.Irvar): i_comp_val, # dyspnoea (self.H): h_comp_val, # cough (self.A): a_comp_val, # smoke (self.B): b_comp_val, # bronchitis (self.C): c_comp_val, # lung (self.D): d_comp_val, # either (self.F): f_comp_val, # tuberculosis (self.G): g_comp_val, # x ray } def test_id(self): """""" self.assertEqual(self.cowell.id(), "cowell") def test_nb_chain_components(self): """""" nb = self.cowell.nb_components self.assertEqual(nb, 8) def test_ccomponents(self): """""" ccomps_nds = set([ set(s).pop() for s in self.cowell.ccomponents if isinstance(s, frozenset) ]) ccomps_undi = [ s for s in self.cowell.ccomponents if isinstance(s, UndiGraph) ].pop() self.assertEqual( ccomps_nds, set([self.A, self.B, self.C, self.E, self.F, self.D, self.G]), ) self.assertEqual(BaseGraphOps.nodes(ccomps_undi), set([self.H, self.Irvar])) def test_get_chain_dag(self): """""" dag_comps = self.cowell.dag_components self.assertEqual(len(BaseGraphOps.nodes(dag_comps)), 8) def test_parents_of_K(self): """""" ccomps_undi = [ s for s in enumerate(self.cowell.ccomponents) if isinstance(s[1], UndiGraph) ].pop() parents_k = self.cowell.parents_of_K(ccomps_undi[0]) self.assertEqual(parents_k, set([self.B, self.D])) ccomps_undi = [ s for s in enumerate(self.koller.ccomponents) if isinstance(s[1], frozenset) ] parents = set() for c in ccomps_undi: obj = set(c[1]).pop() parent = self.koller.parents_of_K(c[0]) parents.add(frozenset([obj, frozenset(parent)])) self.assertEqual( parents, set([ frozenset([self.B, frozenset()]), frozenset([self.A, frozenset()]), frozenset([self.H, frozenset()]), frozenset([self.Irvar, frozenset([self.H, self.C, self.E])]), ]), ) def test_K(self): """""" ccomps_undi = [ s for s in enumerate(self.cowell.ccomponents) if isinstance(s[1], UndiGraph) ] hi = self.cowell.K(ccomps_undi[0][0]) self.assertEqual(BaseGraphOps.nodes(hi), set([self.H, self.Irvar])) def test_moralize(self): """! Test according to figure 4.15 in Koller, Friedman 2009, p. 149 """ moral = self.koller.moralize() koller_moralized = set([ frozenset([self.A.id(), self.B.id()]), frozenset([self.A.id(), self.C.id()]), frozenset([self.C.id(), self.F.id()]), frozenset([self.C.id(), self.D.id()]), frozenset([self.C.id(), self.E.id()]), frozenset([self.C.id(), self.Irvar.id()]), frozenset([self.C.id(), self.H.id()]), frozenset([self.D.id(), self.E.id()]), frozenset([self.D.id(), self.G.id()]), frozenset([self.F.id(), self.G.id()]), frozenset([self.E.id(), self.Irvar.id()]), frozenset([self.B.id(), self.E.id()]), frozenset([self.E.id(), self.H.id()]), frozenset([self.H.id(), self.Irvar.id()]), ]) medges = BaseGraphOps.edges(moral) ms = set([frozenset([m.start().id(), m.end().id()]) for m in medges]) # [print(m) for m in ms] self.assertEqual( ms, koller_moralized, ) def test_cond_prod_by_variable_elimination_evidence(self): """!""" qs = set([self.B]) evs = set([("E", True), ("A", True), ("G", False)]) moral = self.cowell p, a = moral.cond_prod_by_variable_elimination(qs, evs) # check if it is a valid distribution s = 0 for ps in p.factor_domain(): pss = set(ps) f = round(p.phi_normal(pss), 4) s += f if set([("A", True)]) == pss: self.assertEqual(f, 0.01) elif set([("A", False)]) == pss: self.assertEqual(f, 0.99) self.assertTrue(s, 1.0) def test_cond_prod_by_variable_elimination(self): """! Test values taken from Cowell 2005, p. 116, table 6.9 """ e_comp_val = [("E", True, 0.01), ("E", False, 0.99)] i_comp_val = [("I", True, 0.7468), ("I", False, 0.2532)] h_comp_val = [("H", True, 0.7312), ("H", False, 0.2688)] c_comp_val = [("C", True, 0.055), ("C", False, 0.945)] a_comp_val = [("A", True, 0.5), ("A", False, 0.5)] b_comp_val = [("B", True, 0.45), ("B", False, 0.55)] d_comp_val = [("D", True, 0.0648), ("D", False, 0.9352)] f_comp_val = [("F", True, 0.0104), ("F", False, 0.9896)] q_tsts = { (self.E): e_comp_val, (self.Irvar): i_comp_val, # dyspnoea (self.H): h_comp_val, # cough (self.A): a_comp_val, # smoke (self.B): b_comp_val, # bronchitis (self.C): c_comp_val, # lung (self.D): d_comp_val, # either (self.F): f_comp_val, # tuberculosis } evs = set() for q, cvals in q_tsts.items(): final_factor, a = self.cowell.cond_prod_by_variable_elimination( set([q]), evs) s = 0 for cval in cvals: cname = cval[0] c_v = cval[1] c_a = cval[2] cs = set([(cname, c_v)]) f = round(final_factor.phi_normal(cs), 4) s += f self.assertEqual(c_a, f) self.assertEqual(s, 1) def test_cond_prod_by_variable_elimination_evidences_B(self): """! Test values taken from Cowell 2005, p. 119, table 6.12 """ comp_vals = self.q_tsts[self.B] final_factor, a = self.cowell.cond_prod_by_variable_elimination( set([self.B]), self.evidences) for e_val in comp_vals: ename = e_val[0] e_v = e_val[1] f = round(final_factor.phi_normal(set([(ename, e_v)])), 4) self.assertEqual(f, e_val[2]) def test_cond_prod_by_variable_elimination_evidences_I(self): """! Test values taken from Cowell 2005, p. 119, table 6.12 """ comp_vals = self.q_tsts[self.Irvar] final_factor, a = self.cowell.cond_prod_by_variable_elimination( set([self.Irvar]), self.evidences) for e_val in comp_vals: ename = e_val[0] e_v = e_val[1] f = round(final_factor.phi_normal(set([(ename, e_v)])), 4) self.assertEqual(f, e_val[2]) def test_cond_prod_by_variable_elimination_evidences_H(self): """! Test values taken from Cowell 2005, p. 119, table 6.12 """ comp_vals = self.q_tsts[self.H] final_factor, a = self.cowell.cond_prod_by_variable_elimination( set([self.H]), self.evidences) for e_val in comp_vals: ename = e_val[0] e_v = e_val[1] f = round(final_factor.phi_normal(set([(ename, e_v)])), 4) self.assertEqual(f, e_val[2]) def test_cond_prod_by_variable_elimination_evidences_C(self): """! Test values taken from Cowell 2005, p. 119, table 6.12 """ comp_vals = self.q_tsts[self.C] final_factor, a = self.cowell.cond_prod_by_variable_elimination( set([self.C]), self.evidences) for e_val in comp_vals: ename = e_val[0] e_v = e_val[1] f = round(final_factor.phi_normal(set([(ename, e_v)])), 4) self.assertEqual(f, e_val[2]) def test_cond_prod_by_variable_elimination_evidences_F(self): """! Test values taken from Cowell 2005, p. 119, table 6.12 """ comp_vals = self.q_tsts[self.F] final_factor, a = self.cowell.cond_prod_by_variable_elimination( set([self.F]), self.evidences) for e_val in comp_vals: ename = e_val[0] e_v = e_val[1] f = round(final_factor.phi_normal(set([(ename, e_v)])), 4) self.assertEqual(f, e_val[2]) @unittest.skip("unfinished test") def test_most_probable_assignment(self): """! From Cowell 2005, p. 119 """ assignments, factors, z_phi = self.cowell.max_product_ve(set()) def test_mpe_prob_no_evidence(self): """! From Cowell 2005, p. 119 """ cval = 0.2063 prob = self.cowell.mpe_prob(set()) self.assertEqual(round(prob, 4), cval) def test_mpe_prob_evidence(self): """! From Cowell 2005, p. 119 """ cval = 0.002 evs = set([("E", True), ("A", True), ("G", False)]) prob = self.cowell.mpe_prob(evs) self.assertEqual(round(prob, 4), cval) def test_max_product_ve_evidence(self): """! From Cowell 2005, p. 119 """ cval = { "B": True, "A": True, "C": False, "D": False, "F": False, "H": True, "G": False, "I": True, "E": True, } evs = set([("E", True), ("A", True), ("G", False)]) assignments, factors, z_phi = self.cowell.max_product_ve(evs) self.assertEqual(assignments, cval)
def data_1(self): """""" input_data = { "intelligence": { "outcome-values": [0.1, 0.9], "evidence": 0.9 }, "grade": { "outcome-values": [0.2, 0.4, 0.6], "evidence": 0.2 }, "dice": { "outcome-values": [i for i in range(1, 7)], "evidence": 1.0 / 6, }, "fdice": { "outcome-values": [i for i in range(1, 7)] }, } def intelligence_dist(intelligence_value: float): if intelligence_value == 0.1: return 0.7 elif intelligence_value == 0.9: return 0.3 else: return 0 def grade_dist(grade_value: float): if grade_value == 0.2: return 0.25 elif grade_value == 0.4: return 0.37 elif grade_value == 0.6: return 0.38 else: return 0 def fair_dice_dist(dice_value: float): if dice_value in [i for i in range(1, 7)]: return 1.0 / 6.0 else: return 0 def f_dice_dist(dice_value: float): if dice_value in [i for i in range(1, 5)]: return 0.2 else: return 0.2 # intelligence # grade self.intelligence = NumCatRVariable( node_id="int", input_data=input_data["intelligence"], marginal_distribution=intelligence_dist, ) nid2 = "grade" self.grade = NumCatRVariable( node_id=nid2, input_data=input_data["grade"], marginal_distribution=grade_dist, ) nid3 = "dice" self.dice = NumCatRVariable( node_id=nid3, input_data=input_data["dice"], marginal_distribution=fair_dice_dist, ) nid4 = "fdice" self.fdice = NumCatRVariable( node_id=nid4, input_data=input_data["fdice"], marginal_distribution=f_dice_dist, ) self.f = Factor(gid="f", scope_vars=set( [self.grade, self.dice, self.intelligence])) self.f2 = Factor(gid="f2", scope_vars=set([self.grade, self.fdice]))
class TestFactor(unittest.TestCase): """!""" def data_1(self): """""" input_data = { "intelligence": { "outcome-values": [0.1, 0.9], "evidence": 0.9 }, "grade": { "outcome-values": [0.2, 0.4, 0.6], "evidence": 0.2 }, "dice": { "outcome-values": [i for i in range(1, 7)], "evidence": 1.0 / 6, }, "fdice": { "outcome-values": [i for i in range(1, 7)] }, } def intelligence_dist(intelligence_value: float): if intelligence_value == 0.1: return 0.7 elif intelligence_value == 0.9: return 0.3 else: return 0 def grade_dist(grade_value: float): if grade_value == 0.2: return 0.25 elif grade_value == 0.4: return 0.37 elif grade_value == 0.6: return 0.38 else: return 0 def fair_dice_dist(dice_value: float): if dice_value in [i for i in range(1, 7)]: return 1.0 / 6.0 else: return 0 def f_dice_dist(dice_value: float): if dice_value in [i for i in range(1, 5)]: return 0.2 else: return 0.2 # intelligence # grade self.intelligence = NumCatRVariable( node_id="int", input_data=input_data["intelligence"], marginal_distribution=intelligence_dist, ) nid2 = "grade" self.grade = NumCatRVariable( node_id=nid2, input_data=input_data["grade"], marginal_distribution=grade_dist, ) nid3 = "dice" self.dice = NumCatRVariable( node_id=nid3, input_data=input_data["dice"], marginal_distribution=fair_dice_dist, ) nid4 = "fdice" self.fdice = NumCatRVariable( node_id=nid4, input_data=input_data["fdice"], marginal_distribution=f_dice_dist, ) self.f = Factor(gid="f", scope_vars=set( [self.grade, self.dice, self.intelligence])) self.f2 = Factor(gid="f2", scope_vars=set([self.grade, self.fdice])) def data_2(self): """""" # Koller, Friedman 2009, p. 104 self.Af = NumCatRVariable( node_id="A", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Bf = NumCatRVariable( node_id="B", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Cf = NumCatRVariable( node_id="C", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Df = NumCatRVariable( node_id="D", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) def phiAB(scope_product): """""" sfs = set(scope_product) if sfs == set([("A", 10), ("B", 10)]): return 30 elif sfs == set([("A", 10), ("B", 50)]): return 5 elif sfs == set([("A", 50), ("B", 10)]): return 1 elif sfs == set([("A", 50), ("B", 50)]): return 10 else: raise ValueError("unknown arg") self.AB = Factor(gid="AB", scope_vars=set([self.Af, self.Bf]), factor_fn=phiAB) def phiBC(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 100 elif sfs == set([("B", 10), ("C", 50)]): return 1 elif sfs == set([("B", 50), ("C", 10)]): return 1 elif sfs == set([("B", 50), ("C", 50)]): return 100 else: raise ValueError("unknown arg") self.BC = Factor(gid="BC", scope_vars=set([self.Bf, self.Cf]), factor_fn=phiBC) def data_3(self): """""" def phiCD(scope_product): """""" sfs = set(scope_product) if sfs == set([("C", 10), ("D", 10)]): return 1 elif sfs == set([("C", 10), ("D", 50)]): return 100 elif sfs == set([("C", 50), ("D", 10)]): return 100 elif sfs == set([("C", 50), ("D", 50)]): return 1 else: raise ValueError("unknown arg") self.CD = Factor(gid="CD", scope_vars=set([self.Cf, self.Df]), factor_fn=phiCD) def phiDA(scope_product): """""" sfs = set(scope_product) if sfs == set([("D", 10), ("A", 10)]): return 100 elif sfs == set([("D", 10), ("A", 50)]): return 1 elif sfs == set([("D", 50), ("A", 10)]): return 1 elif sfs == set([("D", 50), ("A", 50)]): return 100 else: raise ValueError("unknown arg") self.DA = Factor(gid="DA", scope_vars=set([self.Df, self.Af]), factor_fn=phiDA) def setUp(self): """""" self.data_1() self.data_2() self.data_3() # Koller, Friedman 2009 p. 107 self.af = NumCatRVariable( node_id="A", input_data={"outcome-values": [10, 50, 20]}, marginal_distribution=lambda x: 0.4 if x != 20 else 0.2, ) def phiaB(scope_product): """""" sfs = set(scope_product) if sfs == set([("A", 10), ("B", 10)]): return 0.5 elif sfs == set([("A", 10), ("B", 50)]): return 0.8 elif sfs == set([("A", 50), ("B", 10)]): return 0.1 elif sfs == set([("A", 50), ("B", 50)]): return 0 elif sfs == set([("A", 20), ("B", 10)]): return 0.3 elif sfs == set([("A", 20), ("B", 50)]): return 0.9 else: raise ValueError("unknown arg") self.aB = Factor(gid="ab", scope_vars=set([self.af, self.Bf]), factor_fn=phiaB) def phibc(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 0.5 elif sfs == set([("B", 10), ("C", 50)]): return 0.7 elif sfs == set([("B", 50), ("C", 10)]): return 0.1 elif sfs == set([("B", 50), ("C", 50)]): return 0.2 else: raise ValueError("unknown arg") self.bc = Factor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc) def test_id(self): """""" self.assertEqual(self.f.id(), "f") def test_domain_scope(self): """""" d = self.AB.domain_scope( domain=[set([("A", 50), ("B", 50)]), set([("A", 10), ("B", 10)])]) self.assertEqual(set(d), set([self.Af, self.Bf])) def test_has_var(self): """""" intuple = self.f.has_var(ids="dice") nottuple = self.f.has_var(ids="dice22") self.assertTrue(intuple[0]) self.assertEqual(intuple[1], self.dice) self.assertFalse(nottuple[0]) self.assertEqual(nottuple[1], None) def test_in_scope_t_num(self): self.assertTrue(self.dice in self.f) def test_in_scope_t_str(self): self.assertTrue(self.dice.id() in self.f) def test_in_scope_f_str(self): self.assertFalse("fdsfdsa" in self.f) def test_scope_vars(self): self.assertTrue( self.f.scope_vars(), set([self.dice, self.intelligence, self.grade]), ) def test_marginal_joint(self): """ """ mjoint = self.f.marginal_joint( set([("int", 0.1), ("grade", 0.4), ("dice", 2)])) dmarg = self.dice.marginal(2) imarg = self.intelligence.marginal(0.1) gmarg = self.grade.marginal(0.4) self.assertTrue(mjoint, dmarg * imarg * gmarg) def test_partition_value(self): """""" pval = self.f.partition_value(self.f.vars_domain()) self.assertTrue(pval, 1.0) def test_phi(self): """""" mjoint = self.f.phi(set([("int", 0.1), ("grade", 0.4), ("dice", 2)])) dmarg = self.dice.marginal(2) imarg = self.intelligence.marginal(0.1) gmarg = self.grade.marginal(0.4) self.assertTrue(mjoint, dmarg * imarg * gmarg) def test_phi_normalize(self): mjoint = self.f.phi(set([("int", 0.1), ("grade", 0.4), ("dice", 2)])) dmarg = self.dice.marginal(2) imarg = self.intelligence.marginal(0.1) gmarg = self.grade.marginal(0.4) self.assertTrue(mjoint, (dmarg * imarg * gmarg) / self.f.zval()) def test_from_scope_variables_with_fn(self): """""" A = NumCatRVariable( "A", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.6 if x else 0.4, ) B = NumCatRVariable( "B", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.62 if x else 0.38, ) def phi_ab(scope_product): ss = set(scope_product) if ss == set([("A", True), ("B", True)]): return 0.9 elif ss == set([("A", True), ("B", False)]): return 0.1 elif ss == set([("A", False), ("B", True)]): return 0.2 elif ss == set([("A", False), ("B", False)]): return 0.8 else: raise ValueError("unknown argument") f = Factor.from_scope_variables_with_fn(svars=set([A, B]), fn=phi_ab) query = set([("A", True), ("B", True)]) ff = f.phi(query) self.assertEqual(round(ff, 2), 0.9) @unittest.skip("Factor.from_conditional_vars not yet implemented") def test_from_conditional_vars(self): """""" # A = NumCatRVariable( # "A", # input_data={"outcome-values": [True, False]}, # marginal_distribution=lambda x: 0.6 if x else 0.4, # ) # B = NumCatRVariable( # "B", # input_data={"outcome-values": [True, False]}, # marginal_distribution=lambda x: 0.62 if x else 0.38, # ) def phi_ab(scope_product): ss = set(scope_product) if ss == set([("A", True), ("B", True)]): return 0.9 elif ss == set([("A", True), ("B", False)]): return 0.1 elif ss == set([("A", False), ("B", True)]): return 0.2 elif ss == set([("A", False), ("B", False)]): return 0.8 else: raise ValueError("unknown argument")
class TestFactorOps(unittest.TestCase): """!""" def data_1(self): """""" # Koller, Friedman 2009, p. 104 self.Af = NumCatRVariable( node_id="A", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Bf = NumCatRVariable( node_id="B", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Cf = NumCatRVariable( node_id="C", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) self.Df = NumCatRVariable( node_id="D", input_data={"outcome-values": [10, 50]}, marginal_distribution=lambda x: 0.5, ) def phiAB(scope_product): """""" sfs = set(scope_product) if sfs == set([("A", 10), ("B", 10)]): return 30 elif sfs == set([("A", 10), ("B", 50)]): return 5 elif sfs == set([("A", 50), ("B", 10)]): return 1 elif sfs == set([("A", 50), ("B", 50)]): return 10 else: raise ValueError("unknown arg") self.AB = Factor(gid="AB", scope_vars=set([self.Af, self.Bf]), factor_fn=phiAB) self.AB_b = BaseFactor(gid="AB", scope_vars=set([self.Af, self.Bf]), factor_fn=phiAB) def phiBC(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 100 elif sfs == set([("B", 10), ("C", 50)]): return 1 elif sfs == set([("B", 50), ("C", 10)]): return 1 elif sfs == set([("B", 50), ("C", 50)]): return 100 else: raise ValueError("unknown arg") self.BC = Factor(gid="BC", scope_vars=set([self.Bf, self.Cf]), factor_fn=phiBC) self.BC_b = BaseFactor(gid="BC", scope_vars=set([self.Bf, self.Cf]), factor_fn=phiBC) def data_2(self): """""" def phiCD(scope_product): """""" sfs = set(scope_product) if sfs == set([("C", 10), ("D", 10)]): return 1 elif sfs == set([("C", 10), ("D", 50)]): return 100 elif sfs == set([("C", 50), ("D", 10)]): return 100 elif sfs == set([("C", 50), ("D", 50)]): return 1 else: raise ValueError("unknown arg") self.CD = Factor(gid="CD", scope_vars=set([self.Cf, self.Df]), factor_fn=phiCD) self.CD_b = BaseFactor(gid="CD", scope_vars=set([self.Cf, self.Df]), factor_fn=phiCD) def phiDA(scope_product): """""" sfs = set(scope_product) if sfs == set([("D", 10), ("A", 10)]): return 100 elif sfs == set([("D", 10), ("A", 50)]): return 1 elif sfs == set([("D", 50), ("A", 10)]): return 1 elif sfs == set([("D", 50), ("A", 50)]): return 100 else: raise ValueError("unknown arg") self.DA = Factor(gid="DA", scope_vars=set([self.Df, self.Af]), factor_fn=phiDA) self.DA_b = BaseFactor(gid="DA", scope_vars=set([self.Df, self.Af]), factor_fn=phiDA) def setUp(self): """""" self.data_1() self.data_2() # Koller, Friedman 2009 p. 107 self.af = NumCatRVariable( node_id="A", input_data={"outcome-values": [10, 50, 20]}, marginal_distribution=lambda x: 0.4 if x != 20 else 0.2, ) def phiaB(scope_product): """""" sfs = set(scope_product) if sfs == set([("A", 10), ("B", 10)]): return 0.5 elif sfs == set([("A", 10), ("B", 50)]): return 0.8 elif sfs == set([("A", 50), ("B", 10)]): return 0.1 elif sfs == set([("A", 50), ("B", 50)]): return 0 elif sfs == set([("A", 20), ("B", 10)]): return 0.3 elif sfs == set([("A", 20), ("B", 50)]): return 0.9 else: raise ValueError("unknown arg") self.aB = Factor(gid="ab", scope_vars=set([self.af, self.Bf]), factor_fn=phiaB) self.aB_b = BaseFactor(gid="ab", scope_vars=set([self.af, self.Bf]), factor_fn=phiaB) def phibc(scope_product): """""" sfs = set(scope_product) if sfs == set([("B", 10), ("C", 10)]): return 0.5 elif sfs == set([("B", 10), ("C", 50)]): return 0.7 elif sfs == set([("B", 50), ("C", 10)]): return 0.1 elif sfs == set([("B", 50), ("C", 50)]): return 0.2 else: raise ValueError("unknown arg") self.bc = Factor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc) self.bc_b = BaseFactor(gid="bc", scope_vars=set([self.Bf, self.Cf]), factor_fn=phibc) def test_cls_factor_product(self): "from Koller, Friedman 2009, p. 105, figure 4.2" Ab_Bc, prod1 = FactorOps.cls_product(f=self.AB, other=self.BC) Ab_Bc_Cd, prod2 = FactorOps.cls_product(f=Ab_Bc, other=self.CD) result, prod3 = FactorOps.cls_product(f=Ab_Bc_Cd, other=self.DA) for sm in result.scope_products: sms = set(sm) f = result.phi(sms) ff = round(result.phi_normal(sms), 6) if sms == set([("B", 50), ("C", 50), ("A", 50), ("D", 10)]): self.assertEqual(f, 100000) self.assertEqual(ff, 0.013885) elif sms == set([("B", 50), ("C", 50), ("A", 50), ("D", 50)]): self.assertEqual(f, 100000) self.assertEqual(ff, 0.013885) elif sms == set([("B", 50), ("C", 50), ("A", 10), ("D", 10)]): self.assertEqual(f, 5000000) self.assertEqual(ff, 0.694267) elif sms == set([("B", 50), ("C", 50), ("A", 10), ("D", 50)]): self.assertEqual(f, 500) self.assertEqual(ff, 6.9e-05) elif sms == set([("B", 50), ("C", 10), ("A", 50), ("D", 10)]): self.assertEqual(f, 10) self.assertEqual(ff, 1e-06) elif sms == set([("B", 50), ("C", 10), ("A", 50), ("D", 50)]): self.assertEqual(f, 100000) self.assertEqual(ff, 0.013885) elif sms == set([("B", 50), ("C", 10), ("A", 10), ("D", 10)]): self.assertEqual(f, 500) self.assertEqual(ff, 6.9e-05) elif sms == set([("B", 50), ("C", 10), ("A", 10), ("D", 50)]): self.assertEqual(f, 500) self.assertEqual(ff, 6.9e-05) elif sms == set([("B", 10), ("C", 50), ("A", 50), ("D", 10)]): self.assertEqual(f, 100) self.assertEqual(ff, 1.4e-05) elif sms == set([("B", 10), ("C", 50), ("A", 50), ("D", 50)]): self.assertEqual(f, 100) self.assertEqual(ff, 1.4e-05) elif sms == set([("B", 10), ("C", 50), ("A", 10), ("D", 10)]): self.assertEqual(f, 300000) self.assertEqual(ff, 0.041656) elif sms == set([("B", 10), ("C", 50), ("A", 10), ("D", 50)]): self.assertEqual(f, 30) self.assertEqual(ff, 4e-06) elif sms == set([("B", 10), ("C", 10), ("A", 50), ("D", 10)]): self.assertEqual(f, 100) self.assertEqual(ff, 1.4e-05) elif sms == set([("B", 10), ("C", 10), ("A", 50), ("D", 50)]): self.assertEqual(f, 1000000) self.assertEqual(ff, 0.138853) elif sms == set([("B", 10), ("C", 10), ("A", 10), ("D", 10)]): self.assertEqual(f, 300000) self.assertEqual(ff, 0.041656) elif sms == set([("B", 10), ("C", 10), ("A", 10), ("D", 50)]): self.assertEqual(f, 300000) self.assertEqual(ff, 0.041656) def test_cls_reduced_by_value(self): "from Koller, Friedman 2009, p. 111 figure 4.5" red = set([("C", 10)]) aB_c, prod = FactorOps.cls_product(f=self.aB, other=self.bc) # print(aB_c.scope_products) nf = FactorOps.cls_reduced_by_value(aB_c, assignments=red) sps = set([frozenset(s) for s in nf.scope_products]) self.assertEqual( sps, set([ frozenset([("A", 10), ("B", 50), ("C", 10)]), frozenset([("A", 10), ("B", 10), ("C", 10)]), frozenset([("B", 50), ("A", 20), ("C", 10)]), frozenset([("B", 10), ("A", 20), ("C", 10)]), frozenset([("A", 50), ("B", 50), ("C", 10)]), frozenset([("A", 50), ("B", 10), ("C", 10)]), ]), ) for p in nf.scope_products: ps = set(p) f = round(nf.phi(ps), 5) if ps == set([("A", 10), ("B", 50), ("C", 10)]): self.assertEqual(f, 0.08) elif ps == set([("A", 10), ("B", 10), ("C", 10)]): self.assertEqual(f, 0.25) elif ps == set([("B", 50), ("A", 20), ("C", 10)]): self.assertEqual(f, 0.09) elif ps == set([("B", 10), ("A", 20), ("C", 10)]): self.assertEqual(f, 0.15) elif ps == set([("A", 50), ("B", 50), ("C", 10)]): self.assertEqual(f, 0.0) elif ps == set([("A", 50), ("B", 10), ("C", 10)]): self.assertEqual(f, 0.05) def test_cls_reduce_by_vars(self): """""" evidence = set([("C", 10), ("D", 50)]) aB_c, prod = FactorOps.cls_product(f=self.aB, other=self.bc) # print(aB_c.scope_products) nf = FactorOps.cls_reduced_by_vars(aB_c, assignments=evidence) sps = set([frozenset(s) for s in nf.scope_products]) self.assertEqual( sps, set([ frozenset([("A", 10), ("B", 50), ("C", 10)]), frozenset([("A", 10), ("B", 10), ("C", 10)]), frozenset([("B", 50), ("A", 20), ("C", 10)]), frozenset([("B", 10), ("A", 20), ("C", 10)]), frozenset([("A", 50), ("B", 50), ("C", 10)]), frozenset([("A", 50), ("B", 10), ("C", 10)]), ]), ) def test_cls_sumout_var(self): "from Koller, Friedman 2009, p. 297 figure 9.7" aB_c, prod = FactorOps.cls_product(f=self.aB, other=self.bc) a_c = FactorOps.cls_sumout_var(aB_c, self.Bf) dset = self.Bf.value_set() for p in a_c.scope_products: ps = set(p) f = round(a_c.phi(ps), 4) diff = ps.difference(dset) if diff == set([("C", 10), ("A", 10)]): self.assertEqual(f, 0.33) elif diff == set([("C", 50), ("A", 10)]): self.assertEqual(f, 0.51) elif diff == set([("C", 10), ("A", 50)]): self.assertEqual(f, 0.05) elif diff == set([("C", 50), ("A", 50)]): self.assertEqual(f, 0.07) elif diff == set([("C", 10), ("A", 20)]): self.assertEqual(f, 0.24) elif diff == set([("C", 50), ("A", 20)]): self.assertEqual(f, 0.39) def test_cls_maxout_var(self): "from Koller, Friedman 2009, p. 555 figure 13.1" aB_c, prod = FactorOps.cls_product(f=self.aB, other=self.bc) a_c = FactorOps.cls_maxout_var(aB_c, self.Bf) dset = self.Bf.value_set() for p in a_c.scope_products: ps = set(p) f = round(a_c.phi(ps), 4) diff = ps.difference(dset) if diff == set([("C", 10), ("A", 10)]): self.assertEqual(f, 0.25) elif diff == set([("C", 50), ("A", 10)]): self.assertEqual(f, 0.35) elif diff == set([("C", 10), ("A", 50)]): self.assertEqual(f, 0.05) elif diff == set([("C", 50), ("A", 50)]): self.assertEqual(f, 0.07) elif diff == set([("C", 10), ("A", 20)]): self.assertEqual(f, 0.15) elif diff == set([("C", 50), ("A", 20)]): self.assertEqual(f, 0.21)
def setUp(self): nid1 = "rvar1" input_data = { "intelligence": { "outcome-values": [0.1, 0.9], "evidence": 0.9 }, "grade": { "outcome-values": [0.2, 0.4, 0.6], "evidence": 0.2 }, "dice": { "outcome-values": [i for i in range(1, 7)], "evidence": 1.0 / 6, }, } def intelligence_dist(intelligence_value: float): if intelligence_value == 0.1: return 0.7 elif intelligence_value == 0.9: return 0.3 else: raise ValueError( "intelligence_value does not belong to possible outcomes") def grade_dist(grade_value: float): if grade_value == 0.2: return 0.25 elif grade_value == 0.4: return 0.37 elif grade_value == 0.6: return 0.38 else: raise ValueError("unknown grade value") def fair_dice_dist(dice_value: float): if dice_value in [i for i in range(1, 7)]: return 1.0 / 6.0 else: raise ValueError("dice value") # intelligence # grade self.intelligence = NumCatRVariable( node_id=nid1, input_data=input_data["intelligence"], marginal_distribution=intelligence_dist, ) nid2 = "rvar2" self.grade = NumCatRVariable( node_id=nid2, input_data=input_data["grade"], marginal_distribution=grade_dist, ) nid3 = "rvar3" self.dice = NumCatRVariable( node_id=nid3, input_data=input_data["dice"], marginal_distribution=fair_dice_dist, ) # students = PossibleOutcomes(frozenset(["student_1", "student_2"])) def grade_f(x): return "F" if x == "student_1" else "A" def grade_distribution(x): return 0.1 if x == "F" else 0.9 indata = {"possible-outcomes": students} self.rvar = CatRandomVariable( input_data=indata, node_id="myrandomvar", f=grade_f, marginal_distribution=grade_distribution, )
def setUp(self): """""" idata = { "A": {"outcome-values": [True, False]}, "B": {"outcome-values": [True, False]}, "C": {"outcome-values": [True, False]}, "D": {"outcome-values": [True, False]}, } # misconception example: Koller, Friedman, 2009 p. 104 self.A = NumCatRVariable( node_id="A", input_data=idata["A"], marginal_distribution=lambda x: 0.5, ) self.B = NumCatRVariable( node_id="B", input_data=idata["B"], marginal_distribution=lambda x: 0.5, ) self.C = NumCatRVariable( node_id="C", input_data=idata["C"], marginal_distribution=lambda x: 0.5, ) self.D = NumCatRVariable( node_id="D", input_data=idata["D"], marginal_distribution=lambda x: 0.5, ) self.AB = Edge( edge_id="AB", edge_type=EdgeType.UNDIRECTED, start_node=self.A, end_node=self.B, ) self.AD = Edge( edge_id="AD", edge_type=EdgeType.UNDIRECTED, start_node=self.A, end_node=self.D, ) self.DC = Edge( edge_id="DC", edge_type=EdgeType.UNDIRECTED, start_node=self.D, end_node=self.C, ) self.BC = Edge( edge_id="BC", edge_type=EdgeType.UNDIRECTED, start_node=self.B, end_node=self.C, ) def phi_AB(scope_product): """""" ss = frozenset(scope_product) if ss == frozenset([("A", False), ("B", False)]): return 30.0 elif ss == frozenset([("A", False), ("B", True)]): return 5.0 elif ss == frozenset([("A", True), ("B", False)]): return 1.0 elif ss == frozenset([("A", True), ("B", True)]): return 10.0 else: raise ValueError("product error") def phi_BC(scope_product): """""" ss = frozenset(scope_product) if ss == frozenset([("B", False), ("C", False)]): return 100.0 elif ss == frozenset([("B", False), ("C", True)]): return 1.0 elif ss == frozenset([("B", True), ("C", False)]): return 1.0 elif ss == frozenset([("B", True), ("C", True)]): return 100.0 else: raise ValueError("product error") def phi_CD(scope_product): """""" ss = frozenset(scope_product) if ss == frozenset([("C", False), ("D", False)]): return 1.0 elif ss == frozenset([("C", False), ("D", True)]): return 100.0 elif ss == frozenset([("C", True), ("D", False)]): return 100.0 elif ss == frozenset([("C", True), ("D", True)]): return 1.0 else: raise ValueError("product error") def phi_DA(scope_product): """""" ss = frozenset(scope_product) if ss == frozenset([("D", False), ("A", False)]): return 100.0 elif ss == frozenset([("D", False), ("A", True)]): return 1.0 elif ss == frozenset([("D", True), ("A", False)]): return 1.0 elif ss == frozenset([("D", True), ("A", True)]): return 100.0 else: raise ValueError("product error") self.AB_f = Factor( gid="ab_f", scope_vars=set([self.A, self.B]), factor_fn=phi_AB ) self.BC_f = Factor( gid="bc_f", scope_vars=set([self.B, self.C]), factor_fn=phi_BC ) self.CD_f = Factor( gid="cd_f", scope_vars=set([self.C, self.D]), factor_fn=phi_CD ) self.DA_f = Factor( gid="da_f", scope_vars=set([self.D, self.A]), factor_fn=phi_DA ) self.mnetwork = MarkovNetwork( gid="mnet", nodes=set([self.A, self.B, self.C, self.D]), edges=set([self.AB, self.AD, self.BC, self.DC]), factors=set([self.DA_f, self.CD_f, self.BC_f, self.AB_f]), ) # CH-Asia values from Cowell 2005, p. 116 table 6.9 self.a = NumCatRVariable( node_id="a", input_data=idata["A"], marginal_distribution=lambda x: 0.01 if x else 0.99, ) self.b = NumCatRVariable( node_id="b", input_data=idata["B"], marginal_distribution=lambda x: 0.5, ) self.d = NumCatRVariable( node_id="d", input_data=idata["A"], marginal_distribution=lambda x: 0.7468 if x else 0.2532, ) self.c = NumCatRVariable( node_id="c", input_data=idata["A"], marginal_distribution=lambda x: 0.7312 if x else 0.2688, ) self.ab = Edge( "ab", start_node=self.a, end_node=self.b, edge_type=EdgeType.UNDIRECTED, ) self.ad = Edge( "ad", start_node=self.a, end_node=self.d, edge_type=EdgeType.UNDIRECTED, ) self.bc = Edge( "bc", start_node=self.b, end_node=self.c, edge_type=EdgeType.UNDIRECTED, ) self.dc = Edge( "dc", start_node=self.d, end_node=self.c, edge_type=EdgeType.UNDIRECTED, ) self.ugraph = UndiGraph( "ug1", data={"m": "f"}, nodes=set([self.a, self.b, self.c, self.d]), edges=set([self.ab, self.ad, self.bc, self.dc]), ) # # Conditional Random Field test # from Koller, Friedman 2009, p. 144-145, example 4.20 self.X_1 = NumCatRVariable( node_id="X_1", input_data=idata["A"], marginal_distribution=lambda x: 0.5, ) self.X_2 = NumCatRVariable( node_id="X_2", input_data=idata["A"], marginal_distribution=lambda x: 0.5, ) self.X_3 = NumCatRVariable( node_id="X_3", input_data=idata["A"], marginal_distribution=lambda x: 0.5, ) self.Y_1 = NumCatRVariable( node_id="Y_1", input_data=idata["A"], marginal_distribution=lambda x: 0.5, ) self.X1_Y1 = Edge( edge_id="X1_Y1", edge_type=EdgeType.UNDIRECTED, start_node=self.X_1, end_node=self.Y_1, ) self.X2_Y1 = Edge( edge_id="X2_Y1", edge_type=EdgeType.UNDIRECTED, start_node=self.X_2, end_node=self.Y_1, ) self.X3_Y1 = Edge( edge_id="X3_Y1", edge_type=EdgeType.UNDIRECTED, start_node=self.X_3, end_node=self.Y_1, ) def phi_X1_Y1(scope_product): """""" w = 0.5 ss = frozenset(scope_product) if ss == frozenset([("X_1", True), ("Y_1", True)]): return math.exp(1.0 * w) else: return math.exp(0.0) def phi_X2_Y1(scope_product): """""" w = 5.0 ss = frozenset(scope_product) if ss == frozenset([("X_2", True), ("Y_1", True)]): return math.exp(1.0 * w) else: return math.exp(0.0) def phi_X3_Y1(scope_product): """""" w = 9.4 ss = frozenset(scope_product) if ss == frozenset([("X_3", True), ("Y_1", True)]): return math.exp(1.0 * w) else: return math.exp(0.0) def phi_Y1(scope_product): """""" w = 0.6 ss = frozenset(scope_product) if ss == frozenset([("Y_1", True)]): return math.exp(1.0 * w) else: return math.exp(0.0) self.X1_Y1_f = Factor( gid="x1_y1_f", scope_vars=set([self.X_1, self.Y_1]), factor_fn=phi_X1_Y1, ) self.X2_Y1_f = Factor( gid="x2_y1_f", scope_vars=set([self.X_2, self.Y_1]), factor_fn=phi_X2_Y1, ) self.X3_Y1_f = Factor( gid="x3_y1_f", scope_vars=set([self.X_3, self.Y_1]), factor_fn=phi_X3_Y1, ) self.Y1_f = Factor( gid="y1_f", scope_vars=set([self.Y_1]), factor_fn=phi_Y1 ) self.crf_koller = ConditionalRandomField( "crf", observed_vars=set([self.X_1, self.X_2, self.X_3]), target_vars=set([self.Y_1]), edges=set([self.X1_Y1, self.X2_Y1, self.X3_Y1]), factors=set([self.X1_Y1_f, self.X2_Y1_f, self.X3_Y1_f, self.Y1_f]), )
class NumCatRVariableTest(unittest.TestCase): def setUp(self): nid1 = "rvar1" input_data = { "intelligence": { "outcome-values": [0.1, 0.9], "evidence": 0.9 }, "grade": { "outcome-values": [0.2, 0.4, 0.6], "evidence": 0.2 }, "dice": { "outcome-values": [i for i in range(1, 7)], "evidence": 1.0 / 6, }, } def intelligence_dist(intelligence_value: float): if intelligence_value == 0.1: return 0.7 elif intelligence_value == 0.9: return 0.3 else: raise ValueError( "intelligence_value does not belong to possible outcomes") def grade_dist(grade_value: float): if grade_value == 0.2: return 0.25 elif grade_value == 0.4: return 0.37 elif grade_value == 0.6: return 0.38 else: raise ValueError("unknown grade value") def fair_dice_dist(dice_value: float): if dice_value in [i for i in range(1, 7)]: return 1.0 / 6.0 else: raise ValueError("dice value") # intelligence # grade self.intelligence = NumCatRVariable( node_id=nid1, input_data=input_data["intelligence"], marginal_distribution=intelligence_dist, ) nid2 = "rvar2" self.grade = NumCatRVariable( node_id=nid2, input_data=input_data["grade"], marginal_distribution=grade_dist, ) nid3 = "rvar3" self.dice = NumCatRVariable( node_id=nid3, input_data=input_data["dice"], marginal_distribution=fair_dice_dist, ) # students = PossibleOutcomes(frozenset(["student_1", "student_2"])) def grade_f(x): return "F" if x == "student_1" else "A" def grade_distribution(x): return 0.1 if x == "F" else 0.9 indata = {"possible-outcomes": students} self.rvar = CatRandomVariable( input_data=indata, node_id="myrandomvar", f=grade_f, marginal_distribution=grade_distribution, ) def test_id(self): """""" self.assertEqual(self.grade.id(), "rvar2") def test_values(self): self.assertEqual(self.rvar.values(), frozenset(["A", "F"])) def test_value_set(self): self.assertEqual( self.rvar.value_set( value_transform=lambda x: x.lower(), value_filter=lambda x: x != "A", ), frozenset([("myrandomvar", "f")]), ) def test_max_marginal_value(self): self.assertEqual(self.intelligence.max_marginal_value(), 0.1) def test_max(self): self.assertEqual(self.intelligence.max(), 0.7) def test_min(self): self.assertEqual(self.intelligence.min(), 0.3) def test_min_marginal_value(self): self.assertEqual(self.intelligence.min_marginal_value(), 0.9) def test_expected_value(self): """""" self.assertEqual(self.dice.expected_value(), 3.5) def test_marginal_with_known_value(self): """""" self.assertEqual(self.grade.marginal(0.4), 0.37) def test_p_x_known_value(self): """""" self.assertEqual(self.grade.p(0.4), 0.37) def test_P_X_e(self): """""" self.assertEqual(self.grade.P_X_e(), 0.25) def test_max_marginal_e(self): """""" self.assertEqual(self.grade.max_marginal_e(), 0.25) def test_min_marginal_e(self): """""" self.assertEqual(self.grade.min_marginal_e(), 0.25) def test_marginal_over(self): """""" eval_value = 0.2 margover = self.grade.marginal_over(eval_value, self.dice) self.assertEqual(margover, 3.5 * 0.25) def test_marginal_over_evidence_key(self): """""" margover = self.grade.marginal_over_evidence_key(self.dice) self.assertEqual(margover, 3.5 * 0.25) def test_joint_without_evidence(self): dice = self.dice dice.pop_evidence() self.assertEqual(dice.joint(dice), 3.5 * 3.5) def test_variance(self): self.assertEqual(round(self.dice.variance(), 3), 2.917) def test_standard_deviation(self): """""" self.assertEqual( round(self.dice.standard_deviation(), 3), round(math.sqrt(2.917), 3), )
def cls_nodes_1(cls): """""" idata = { "a": { "outcome-values": [True, False] }, "b": { "outcome-values": [True, False] }, "c": { "outcome-values": [True, False] }, } cls.a = NumCatRVariable( node_id="a", input_data=idata["a"], marginal_distribution=lambda x: 0.6 if x else 0.4, ) cls.b = NumCatRVariable( node_id="b", input_data=idata["b"], marginal_distribution=lambda x: 0.5 if x else 0.5, ) cls.c = NumCatRVariable( node_id="c", input_data=idata["c"], marginal_distribution=lambda x: 0.5 if x else 0.5, ) cls.ab = Edge( edge_id="ab", edge_type=EdgeType.UNDIRECTED, start_node=cls.a, end_node=cls.b, ) cls.bc = Edge( edge_id="bc", edge_type=EdgeType.UNDIRECTED, start_node=cls.b, end_node=cls.c, ) def phi_ba(scope_product): """""" ss = set(scope_product) if ss == set([("a", True), ("b", True)]): return 0.9 elif ss == set([("a", True), ("b", False)]): return 0.1 elif ss == set([("a", False), ("b", True)]): return 0.2 elif ss == set([("a", False), ("b", False)]): return 0.8 else: raise ValueError("product error") def phi_cb(scope_product): """""" ss = set(scope_product) if ss == set([("c", True), ("b", True)]): return 0.3 elif ss == set([("c", True), ("b", False)]): return 0.5 elif ss == set([("c", False), ("b", True)]): return 0.7 elif ss == set([("c", False), ("b", False)]): return 0.5 else: raise ValueError("product error") def phi_a(scope_product): s = set(scope_product) if s == set([("a", True)]): return 0.6 elif s == set([("a", False)]): return 0.4 else: raise ValueError("product error") cls.ba_f = Factor(gid="ba", scope_vars=set([cls.b, cls.a]), factor_fn=phi_ba) cls.cb_f = Factor(gid="cb", scope_vars=set([cls.c, cls.b]), factor_fn=phi_cb) cls.a_f = Factor(gid="a", scope_vars=set([cls.a]), factor_fn=phi_a)
def cls_nodes_2(cls): """""" odata = {"outcome-values": [True, False]} cls.J = NumCatRVariable(node_id="J", input_data=odata, marginal_distribution=lambda x: 0.5) cls.Irvar = NumCatRVariable(node_id="I", input_data=odata, marginal_distribution=lambda x: 0.5) cls.X = NumCatRVariable(node_id="X", input_data=odata, marginal_distribution=lambda x: 0.5) cls.Y = NumCatRVariable(node_id="Y", input_data=odata, marginal_distribution=lambda x: 0.5) cls.Orvar = NumCatRVariable(node_id="O", input_data=odata, marginal_distribution=lambda x: 0.5) cls.JX = Edge( edge_id="JX", edge_type=EdgeType.DIRECTED, start_node=cls.J, end_node=cls.X, ) cls.JY = Edge( edge_id="JY", edge_type=EdgeType.DIRECTED, start_node=cls.J, end_node=cls.Y, ) cls.IX = Edge( edge_id="IX", edge_type=EdgeType.DIRECTED, start_node=cls.Irvar, end_node=cls.X, ) cls.XO = Edge( edge_id="XO", edge_type=EdgeType.DIRECTED, start_node=cls.X, end_node=cls.Orvar, ) cls.YO = Edge( edge_id="YO", edge_type=EdgeType.DIRECTED, start_node=cls.Y, end_node=cls.Orvar, ) def phi_ij(scope_product, i: str): """""" ss = set(scope_product) if ss == set([(i, True)]): return 0.5 elif ss == set([(i, False)]): return 0.5 else: raise ValueError("unknown scope product") def phi_i(scope_product): """""" return phi_ij(scope_product, i="I") cls.I_f = Factor(gid="I_f", scope_vars=set([cls.Irvar]), factor_fn=phi_i) def phi_j(scope_product): """""" return phi_ij(scope_product, i="J") cls.J_f = Factor(gid="J_f", scope_vars=set([cls.J]), factor_fn=phi_j) def phi_jy(scope_product): """""" ss = set(scope_product) if ss == set([("J", True), ("Y", True)]): return 0.01 elif ss == set([("J", True), ("Y", False)]): return 0.99 elif ss == set([("J", False), ("Y", True)]): return 0.99 elif ss == set([("J", False), ("Y", False)]): return 0.01 else: raise ValueError("scope product unknown") cls.JY_f = Factor(gid="JY_f", scope_vars=set([cls.J, cls.Y]), factor_fn=phi_jy)
def test_from_digraph_with_factors(self): """! Values from Darwiche 2009, p. 132, figure 6.4 """ A = NumCatRVariable( "A", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.6 if x else 0.4, ) B = NumCatRVariable( "B", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.62 if x else 0.38, ) C = NumCatRVariable( "C", input_data={"outcome-values": [True, False]}, marginal_distribution=lambda x: 0.624 if x else 0.376, ) AB_Edge = Edge( edge_id="ab_edge", start_node=A, end_node=B, edge_type=EdgeType.DIRECTED, ) BC_Edge = Edge( edge_id="bc_edge", start_node=B, end_node=C, edge_type=EdgeType.DIRECTED, ) def phi_a(scope_product): """""" ss = set(scope_product) if ss == set([("A", True)]): return 0.6 elif ss == set([("A", False)]): return 0.4 else: raise ValueError("unknown argument") def phi_ab(scope_product): ss = set(scope_product) if ss == set([("A", True), ("B", True)]): return 0.9 elif ss == set([("A", True), ("B", False)]): return 0.1 elif ss == set([("A", False), ("B", True)]): return 0.2 elif ss == set([("A", False), ("B", False)]): return 0.8 else: raise ValueError("unknown argument") def phi_bc(scope_product): ss = set(scope_product) if ss == set([("C", True), ("B", True)]): return 0.3 elif ss == set([("C", True), ("B", False)]): return 0.5 elif ss == set([("C", False), ("B", True)]): return 0.7 elif ss == set([("C", False), ("B", False)]): return 0.5 else: raise ValueError("unknown argument") A_f = Factor(gid="A_f", scope_vars=set([A]), factor_fn=phi_a) AB_f = Factor(gid="AB_f", scope_vars=set([A, B]), factor_fn=phi_ab) BC_f = Factor(gid="BC_f", scope_vars=set([C, B]), factor_fn=phi_bc) dig = DiGraph(gid="temp", nodes=set([A, B, C]), edges=set([AB_Edge, BC_Edge])) factors = set([A_f, AB_f, BC_f]) bn = BayesianNetwork( gid="temp", nodes=set([A, B, C]), edges=set([AB_Edge, BC_Edge]), factors=set([A_f, AB_f, BC_f]), ) q = set([B]) evidence = set([]) foo, a = bn.cond_prod_by_variable_elimination(queries=q, evidences=evidence) bayes = BayesianNetwork.from_digraph(dig, factors) foo2, a2 = bayes.cond_prod_by_variable_elimination(queries=q, evidences=evidence) f1 = set([("B", False)]) self.assertEqual(foo.phi(f1), foo2.phi(f1)) f1 = set([("B", True)]) self.assertEqual(foo.phi(f1), foo2.phi(f1))
def setUp(self): """""" idata = { "rain": { "outcome-values": [True, False] }, "sprink": { "outcome-values": [True, False] }, "wet": { "outcome-values": [True, False] }, "road": { "outcome-values": [True, False] }, "winter": { "outcome-values": [True, False] }, "earthquake": { "outcome-values": [True, False] }, "burglary": { "outcome-values": [True, False] }, "alarm": { "outcome-values": [True, False] }, } self.rain = NumCatRVariable( input_data=idata["rain"], node_id="rain", marginal_distribution=lambda x: 0.2 if x is True else 0.8, ) self.sprink = NumCatRVariable( node_id="sprink", input_data=idata["sprink"], marginal_distribution=lambda x: 0.6 if x is True else 0.4, ) self.wet = NumCatRVariable( node_id="wet", input_data=idata["wet"], marginal_distribution=lambda x: 0.7 if x is True else 0.3, ) self.rain_wet = Edge( edge_id="rain_wet", start_node=self.rain, end_node=self.wet, edge_type=EdgeType.DIRECTED, ) self.rain_sprink = Edge( edge_id="rain_sprink", start_node=self.rain, end_node=self.sprink, edge_type=EdgeType.DIRECTED, ) self.sprink_wet = Edge( edge_id="sprink_wet", start_node=self.sprink, end_node=self.wet, edge_type=EdgeType.DIRECTED, ) def sprink_rain_factor(scope_product): """""" sfs = set(scope_product) if sfs == set([("rain", True), ("sprink", True)]): return 0.01 elif sfs == set([("rain", True), ("sprink", False)]): return 0.99 elif sfs == set([("rain", False), ("sprink", True)]): return 0.4 elif sfs == set([("rain", False), ("sprink", False)]): return 0.6 else: raise ValueError("unknown product") self.rain_sprink_f = Factor.from_scope_variables_with_fn( svars=set([self.rain, self.sprink]), fn=sprink_rain_factor) def grass_wet_factor(scope_product): """""" sfs = set(scope_product) if sfs == set([("rain", False), ("sprink", False), ("wet", True)]): return 0.0 elif sfs == set([("rain", False), ("sprink", False), ("wet", False)]): return 1.0 elif sfs == set([("rain", False), ("sprink", True), ("wet", True)]): return 0.8 elif sfs == set([("rain", False), ("sprink", True), ("wet", False)]): return 0.2 elif sfs == set([("rain", True), ("sprink", False), ("wet", True)]): return 0.9 elif sfs == set([("rain", True), ("sprink", False), ("wet", False)]): return 0.1 elif sfs == set([("rain", True), ("sprink", True), ("wet", True)]): return 0.99 elif sfs == set([("rain", True), ("sprink", True), ("wet", False)]): return 0.01 else: raise ValueError("unknown product") self.grass_wet_f = Factor.from_scope_variables_with_fn( svars=set([self.rain, self.sprink, self.wet]), fn=grass_wet_factor) self.bayes = BayesianNetwork( gid="b", nodes=set([self.rain, self.sprink, self.wet]), edges=set([self.rain_wet, self.rain_sprink, self.sprink_wet]), factors=set([self.grass_wet_f, self.rain_sprink_f]), ) # # Darwiche 2009, p. 30 # # Earthquake Burglary # \ / # \ / # Alarm # self.EarthquakeN = NumCatRVariable( input_data=idata["earthquake"], node_id="EarthquakeN", marginal_distribution=lambda x: 0.1 if x is True else 0.9, ) self.BurglaryN = NumCatRVariable( input_data=idata["burglary"], node_id="BurglaryN", marginal_distribution=lambda x: 0.2 if x is True else 0.8, ) self.AlarmN = NumCatRVariable( input_data=idata["alarm"], node_id="AlarmN", marginal_distribution=lambda x: 0.2442 if x is True else 0.7558, ) self.burglar_alarm = Edge( edge_id="burglar_alarm", start_node=self.BurglaryN, end_node=self.AlarmN, edge_type=EdgeType.DIRECTED, ) self.earthquake_alarm = Edge( edge_id="earthquake_alarm", start_node=self.EarthquakeN, end_node=self.AlarmN, edge_type=EdgeType.DIRECTED, ) idata = {"outcome-values": [True, False]} self.C = NumCatRVariable(node_id="C", input_data=idata, marginal_distribution=lambda x: 0.5) self.E = NumCatRVariable(node_id="E", input_data=idata, marginal_distribution=lambda x: 0.5) self.F = NumCatRVariable(node_id="F", input_data=idata, marginal_distribution=lambda x: 0.5) self.D = NumCatRVariable(node_id="D", input_data=idata, marginal_distribution=lambda x: 0.5) self.CE = Edge( edge_id="CE", start_node=self.C, end_node=self.E, edge_type=EdgeType.DIRECTED, ) self.ED = Edge( edge_id="ED", start_node=self.E, end_node=self.D, edge_type=EdgeType.DIRECTED, ) self.EF = Edge( edge_id="EF", start_node=self.E, end_node=self.F, edge_type=EdgeType.DIRECTED, ) def phi_c(scope_product): ss = set(scope_product) if ss == set([("C", True)]): return 0.8 elif ss == set([("C", False)]): return 0.2 else: raise ValueError("scope product unknown") def phi_ec(scope_product): ss = set(scope_product) if ss == set([("C", True), ("E", True)]): return 0.9 elif ss == set([("C", True), ("E", False)]): return 0.1 elif ss == set([("C", False), ("E", True)]): return 0.7 elif ss == set([("C", False), ("E", False)]): return 0.3 else: raise ValueError("scope product unknown") def phi_fe(scope_product): ss = set(scope_product) if ss == set([("E", True), ("F", True)]): return 0.9 elif ss == set([("E", True), ("F", False)]): return 0.1 elif ss == set([("E", False), ("F", True)]): return 0.5 elif ss == set([("E", False), ("F", False)]): return 0.5 else: raise ValueError("scope product unknown") def phi_de(scope_product): ss = set(scope_product) if ss == set([("E", True), ("D", True)]): return 0.7 elif ss == set([("E", True), ("D", False)]): return 0.3 elif ss == set([("E", False), ("D", True)]): return 0.4 elif ss == set([("E", False), ("D", False)]): return 0.6 else: raise ValueError("scope product unknown") self.CE_f = Factor(gid="CE_f", scope_vars=set([self.C, self.E]), factor_fn=phi_ec) self.C_f = Factor(gid="C_f", scope_vars=set([self.C]), factor_fn=phi_c) self.FE_f = Factor(gid="FE_f", scope_vars=set([self.F, self.E]), factor_fn=phi_fe) self.DE_f = Factor(gid="DE_f", scope_vars=set([self.D, self.E]), factor_fn=phi_de) self.bayes_n = BayesianNetwork( gid="ba", nodes=set([self.C, self.E, self.D, self.F]), edges=set([self.EF, self.CE, self.ED]), factors=set([self.C_f, self.DE_f, self.CE_f, self.FE_f]), )