Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    def __init__(
        self,
        gid: str,
        nodes: Set[NumCatRVariable],
        edges: Set[Edge],
        factors: Optional[Set[Factor]] = None,
        data={},
    ):
        """!
        \brief constructor for a generic Probabilistic Graphical Model

        The generic model that extends the #Graph definition by adding a new
        set, called set of factors.
        Most of the parameters are documented in #Graph.
        """
        super().__init__(gid=gid, data=data, nodes=nodes, edges=edges)
        if factors is None:
            fs: Set[Factor] = set()
            for e in BaseGraphOps.edges(self):
                estart = e.start()
                eend = e.end()
                sdata = estart.data()
                edata = eend.data()
                evidences = set()
                if "evidence" in sdata:
                    evidences.add((estart.id(), sdata["evidence"]))
                if "evidence" in edata:
                    evidences.add((eend.id(), edata["evidence"]))
                f = Factor(gid=str(uuid4()), scope_vars=set([estart, eend]))
                if len(evidences) != 0:
                    f = f.reduced_by_value(evidences)
                fs.add(f)
            self.Fs = fs
        else:
            self.Fs = factors
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    def cls_nodes_3(cls):
        """"""
        cls.cls_nodes_2()

        def phi_ijx(scope_product):
            """"""
            ss = set(scope_product)
            if ss == set([("I", True), ("J", True), ("X", True)]):
                return 0.95
            elif ss == set([("I", True), ("J", True), ("X", False)]):
                return 0.05
            elif ss == set([("I", True), ("J", False), ("X", True)]):
                return 0.05
            elif ss == set([("I", True), ("J", False), ("X", False)]):
                return 0.95
            elif ss == set([("I", False), ("J", True), ("X", True)]):
                return 0.05
            elif ss == set([("I", False), ("J", True), ("X", False)]):
                return 0.95
            elif ss == set([("I", False), ("J", False), ("X", True)]):
                return 0.05
            elif ss == set([("I", False), ("J", False), ("X", False)]):
                return 0.95
            else:
                raise ValueError("scope product unknown")

        cls.IJX_f = Factor(
            gid="IJX_f",
            scope_vars=set([cls.J, cls.X, cls.Irvar]),
            factor_fn=phi_ijx,
        )

        def phi_xyo(scope_product):
            """"""
            ss = set(scope_product)
            if ss == set([("X", True), ("Y", True), ("O", True)]):
                return 0.98
            elif ss == set([("X", True), ("Y", True), ("O", False)]):
                return 0.02
            elif ss == set([("X", True), ("Y", False), ("O", True)]):
                return 0.98
            elif ss == set([("X", True), ("Y", False), ("O", False)]):
                return 0.02
            elif ss == set([("X", False), ("Y", True), ("O", True)]):
                return 0.98
            elif ss == set([("X", False), ("Y", True), ("O", False)]):
                return 0.02
            elif ss == set([("X", False), ("Y", False), ("O", True)]):
                return 0.02
            elif ss == set([("X", False), ("Y", False), ("O", False)]):
                return 0.98
            else:
                raise ValueError("scope product unknown")

        cls.XYO_f = Factor(
            gid="XYO_f",
            scope_vars=set([cls.Y, cls.X, cls.Orvar]),
            factor_fn=phi_xyo,
        )
Exemplo n.º 5
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)
Exemplo n.º 6
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)
Exemplo n.º 7
0
 def __init__(self, f):
     """"""
     if isinstance(f, AbstractFactor):
         fac = Factor.from_abstract_factor(f)
     elif isinstance(f, BaseFactor):
         fac = Factor.from_base_factor(f)
     elif isinstance(f, Factor):
         fac = f
     else:
         raise TypeError("argument must inherit from AbstractFactor object")
     self.factor = fac
Exemplo n.º 8
0
    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)
Exemplo n.º 9
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)
Exemplo n.º 10
0
    def cls_sumout_var(cls, f: Factor, Y: NumCatRVariable):
        """!
        \brief Sum the variable out of factor as per Koller, Friedman 2009, p. 297

        Summing out, or factor marginalization, is defined as the following by
        Koller, Friedman:

        <blockquote>

        Let X be a set of variables and Y \f$\not \in \f$ X a variable. Let
        \f$\phi(X, Y)\f] be a factor. We define the factor marginalization of Y
        in phi, denoted \f$ \sum_Y \phi \f$, to be a factor psi over X such
        that: \f$ \psi(X) = \sum_Y \phi(X,Y) \f$

        </blockquote>


        \param Y the variable that we are going to sum out.

        \throw ValueError We raise a value error if the argument is not in
        the scope of this factor

        \return Factor
        """
        if Y not in f:
            msg = "Argument " + str(Y)
            msg += " is not in scope of this factor: "
            msg += " ".join(f.scope_vars())
            raise ValueError(msg)

        # Y_vals = Y.value_set()
        products = f.factor_domain()
        fn = f.factor_fn

        def psi(scope_product: Set[Tuple[str, NumericValue]]):
            """"""
            s = set(scope_product)
            diffs = set([p for p in products if s.issubset(p) is True])
            return sum([fn(d) for d in diffs])

        return Factor(
            gid=str(uuid4()),
            scope_vars=f.scope_vars().difference({Y}),
            factor_fn=psi,
        )
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    def _compare_prob_value(
            cls,
            f: Factor,
            comp_fn: Callable[[float, float],
                              bool] = lambda phi_s, mx: phi_s > mx,
            comp_v: float = float("-inf"),
    ):
        """"""
        if not isinstance(f, Factor):
            raise TypeError("The object must be of Factor type")

        cval = comp_v
        out_val = None
        for sp in f.factor_domain():
            ss = frozenset(sp)
            phi_s = f.phi(ss)
            if comp_fn(phi_s, cval):
                cval = phi_s
                out_val = ss
        return out_val, cval
Exemplo n.º 13
0
    def cls_reduced(cls, f: Factor,
                    assignments: Set[Tuple[str, NumericValue]]) -> Factor:
        """!
        \brief reduce factor using given context

        \param assignments values that are assigned to random variables of this
        factor.

        \return Factor whose conditional probability table rows are shrink to
        rows that contain assignment values.

        Koller, Friedman 2009, p. 111 reduction by value example

        \f$phi(A,B,C)\f$

         A      B      C
        ---- | ---- | ----
         a1  |  b1  |  c1
         a1  |  b1  |  c2
         a2  |  b1  |  c1
         a2  |  b1  |  c2

        reduction C=c1 \f$\phi(A,B,C=c_1)\f$

           A      B      C
          ---- | ---- | ----
           a1  |  b1  |  c1
           a2  |  b1  |  c1

        """
        svars = set()
        for sv in f.scope_vars():
            for kval in assignments:
                k, value = kval
                if sv.id() == k:
                    sv.reduce_to_value(value)
            svars.add(sv)
        return Factor(gid=str(uuid4()), scope_vars=svars, factor_fn=f.phi)
Exemplo n.º 14
0
    def cls_maxout_var(cls, f: Factor, Y: NumCatRVariable):
        """!
        \brief max the variable out of factor as per Koller, Friedman 2009, p. 555

        Maxing out a variable, or factor maximization is defined by Koller,
        Friedman as:
        <blockquote>
        Let X be a set of variables, and Y \f$ \not \in \f$ X, a random
        variable. Let \f$ \phi(X, Y) \f$ be a factor. We define the factor
        maximization of Y in \f$ \phi \f$ to be factor \f$ \psi \f$ over X such
        that: \f$ \psi(X) = max_{Y}\phi(X, Y) \f$
        </blockquote>

        \param Y random variable who is going to be maxed out.

        \throw ValueError If the argument is not in scope of this factor, we
        throw a value error

        \return Factor
        """
        if Y not in f:
            raise ValueError("argument is not in scope of this factor")

        # Y_vals = Y.value_set()
        products = f.factor_domain()
        fn = f.factor_fn

        def psi(scope_product: Set[Tuple[str, NumericValue]]):
            """"""
            s = set(scope_product)
            diffs = set([p for p in products if s.issubset(p) is True])
            return max([fn(d) for d in diffs])

        return Factor(
            gid=str(uuid4()),
            scope_vars=f.scope_vars().difference({Y}),
            factor_fn=psi,
        )
Exemplo n.º 15
0
    def cls_product(
        cls,
        f: Factor,
        other: Factor,
        product_fn=lambda x, y: x * y,
        accumulator=lambda added, accumulated: added * accumulated,
    ) -> Tuple[Factor, float]:
        """!
        \brief Factor product operation from Koller, Friedman 2009, p. 107
        \f$ \psi(X,Y,Z) =  \phi(X,Y) \cdot \phi(Y,Z) \f$
        \f$ \prod_i phi(X_i) \f$

        Point wise product of two different factor functions.

        \param product_fn actual function for computing product. This function
        can be exchanged with another function to compute log-sum for example.

        \param accumulator this function decides how to accumulate resulting product.
        \param product_fn
        \parblock

        product function. Default case is that it multiplies
        its two arguments. In case of a floating precision problem it can be
        changed into summation.

        \endparblock

        \return tuple whose first element is the resulting factor and second
        element is the accumulated product.
        """
        if not isinstance(f, Factor):
            raise TypeError("f argument needs to be a factor")

        if not isinstance(other, Factor):
            raise TypeError("other needs to be a factor")
        #
        svar = f.scope_vars()
        ovar = other.scope_vars()
        var_inter = svar.intersection(ovar)
        var_inter = list(var_inter)
        vsets = [v.value_set() for v in var_inter]
        inter_products = list(product(*vsets))
        smatch = f.factor_domain()
        omatch = other.factor_domain()
        prod = 1.0
        common_match = set()
        for iproduct in inter_products:
            for o in omatch:
                for s in smatch:
                    ss = set(s)
                    ost = set(o)
                    prod_s = set(iproduct)
                    if prod_s.issubset(ss) and prod_s.issubset(ost):
                        common = ss.union(ost)
                        multi = product_fn(f.factor_fn(ss),
                                           other.factor_fn(ost))
                        common_match.add((multi, tuple(common)))
                        prod = accumulator(multi, prod)

        def fx(scope_product: Set[Tuple[str, NumericValue]]):
            """"""
            for multip, match in common_match:
                if set(match) == set(scope_product):
                    return multip

        f = Factor(gid=str(uuid4()), scope_vars=svar.union(ovar), factor_fn=fx)
        return f, prod
Exemplo n.º 16
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)
Exemplo n.º 17
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)
Exemplo n.º 18
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]))
Exemplo n.º 19
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")
Exemplo n.º 20
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]),
        )
Exemplo n.º 21
0
    def from_undigraph(cls, udi: UndiGraph):
        """!
        \brief Make a markov network from undirected graph

        \throws ValueError If nodes are not an instance of a random variable,
        we raise a value error.

        Unless it is specified we assume that edges indicate a joint
        distribution

        \code{.py}

         >>> idata = {"A": {"outcome-values": [True, False]}}
         >>> a = NumCatRVariable(
         >>>     node_id="a",
         >>>     input_data=idata["A"],
         >>>     distribution=lambda x: 0.01 if x else 0.99,
         >>> )
         >>> b = NumCatRVariable(
         >>>     node_id="b", input_data=idata["B"], distribution=lambda x: 0.5
         >>> )
         >>> d = NumCatRVariable(
         >>>     node_id="d",
         >>>     input_data=idata["A"],
         >>>     distribution=lambda x: 0.7468 if x else 0.2532,
         >>> )
         >>> c = NumCatRVariable(
         >>>     node_id="c",
         >>>     input_data=idata["A"],
         >>>     distribution=lambda x: 0.7312 if x else 0.2688,
         >>> )
         >>> ab = Edge(
         >>>     "ab", start_node=a, end_node=b, edge_type=EdgeType.UNDIRECTED
         >>> )
         >>> ad = Edge(
         >>>     "ad", start_node=a, end_node=d, edge_type=EdgeType.UNDIRECTED
         >>> )

         >>> bc = Edge(
         >>>     "bc", start_node=b, end_node=c, edge_type=EdgeType.UNDIRECTED
         >>> )
         >>> dc = Edge(
         >>>     "dc", start_node=d, end_node=c, edge_type=EdgeType.UNDIRECTED
         >>> )
         >>> ugraph = UndiGraph(
         >>>     "ug1",
         >>>     data={"m": "f"},
         >>>     nodes=set([a, b, c, d]),
         >>>     edges=set([ab, ad, bc, dc]),
         >>> )
         >>> markov = MarkovNetwork.from_undigraph(udi=ugraph)

        \endcode
        """
        for n in BaseGraphOps.nodes(udi):
            if not isinstance(n, RandomVariable):
                raise ValueError(
                    "Nodes are not an instance of random variable")
        fs: Set[Factor] = set()
        maximal_cliques = udi.find_maximal_cliques()
        for clique in maximal_cliques:
            evidences = set()
            for n in clique:
                edata = n.data()
                if "evidence" in edata:
                    evidences.add((n.id(), edata["evidence"]))
            f = Factor(gid=str(uuid4()), scope_vars=clique)
            if len(evidences) != 0:
                f = f.reduced_by_value(evidences)
            fs.add(f)
        return MarkovNetwork(
            gid=str(uuid4()),
            nodes=BaseGraphOps.nodes(udi),
            edges=BaseGraphOps.edges(udi),
            factors=fs,
        )
Exemplo n.º 22
0
 def scope_of(self, phi: Factor) -> Set[NumCatRVariable]:
     """!"""
     return phi.scope_vars()
Exemplo n.º 23
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))
Exemplo n.º 24
0
    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)
Exemplo n.º 25
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]),
        )