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)
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
 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,
     )
Example #6
0
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)
Example #7
0
    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]))
Example #8
0
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")
Example #9
0
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,
        )
Example #11
0
    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),
        )
Example #13
0
    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)
Example #14
0
    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)
Example #15
0
    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))
Example #16
0
    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]),
        )