예제 #1
0
    def expectation(self, expr, condition=None, evaluate=True, **kwargs):
        """
        Computes expectation.

        Parameters
        ==========

        expr: RandomIndexedSymbol, Relational, Logic
            Condition for which expectation has to be computed. Must
            contain a RandomIndexedSymbol of the process.
        condition: Relational, Logic
            The given conditions under which computations should be done.

        Returns
        =======

        Expectation of the RandomIndexedSymbol.

        """
        new_expr, new_condition = self._rvindexed_subs(expr, condition)

        new_pspace = pspace(new_expr)
        if new_condition is not None:
            new_expr = given(new_expr, new_condition)
        if new_expr.is_Add:  # As E is Linear
            return Add(*[
                new_pspace.compute_expectation(
                    expr=arg, evaluate=evaluate, **kwargs)
                for arg in new_expr.args
            ])
        return new_pspace.compute_expectation(new_expr,
                                              evaluate=evaluate,
                                              **kwargs)
예제 #2
0
    def doit(self, **hints):
        condition = self.args[0]
        given_condition = self._condition
        numsamples = hints.get('numsamples', False)
        for_rewrite = not hints.get('for_rewrite', False)

        if isinstance(condition, Not):
            return S.One - self.func(condition.args[0],
                                     given_condition,
                                     evaluate=for_rewrite).doit(**hints)

        if condition.has(RandomIndexedSymbol):
            return pspace(condition).probability(condition,
                                                 given_condition,
                                                 evaluate=for_rewrite)

        if isinstance(given_condition, RandomSymbol):
            condrv = random_symbols(condition)
            if len(condrv) == 1 and condrv[0] == given_condition:
                from sympy.stats.frv_types import BernoulliDistribution
                return BernoulliDistribution(
                    self.func(condition).doit(**hints), 0, 1)
            if any([dependent(rv, given_condition) for rv in condrv]):
                return Probability(condition, given_condition)
            else:
                return Probability(condition).doit()

        if given_condition is not None and \
                not isinstance(given_condition, (Relational, Boolean)):
            raise ValueError(
                "%s is not a relational or combination of relationals" %
                (given_condition))

        if given_condition == False or condition is S.false:
            return S.Zero
        if not isinstance(condition, (Relational, Boolean)):
            raise ValueError(
                "%s is not a relational or combination of relationals" %
                (condition))
        if condition is S.true:
            return S.One

        if numsamples:
            return sampling_P(condition,
                              given_condition,
                              numsamples=numsamples)
        if given_condition is not None:  # If there is a condition
            # Recompute on new conditional expr
            return Probability(given(condition, given_condition)).doit()

        # Otherwise pass work off to the ProbabilitySpace
        if pspace(condition) == PSpace():
            return Probability(condition, given_condition)

        result = pspace(condition).probability(condition)
        if hasattr(result, 'doit') and for_rewrite:
            return result.doit()
        else:
            return result
예제 #3
0
    def probability(self,
                    condition,
                    given_condition=None,
                    evaluate=True,
                    **kwargs):
        """
        Computes probability.

        Parameters
        ==========

        condition: Relational
                Condition for which probability has to be computed. Must
                contain a RandomIndexedSymbol of the process.
        given_condition: Relational/And
                The given conditions under which computations should be done.

        Returns
        =======

        Probability of the condition.

        """
        new_condition, new_givencondition = self._rvindexed_subs(
            condition, given_condition)

        if isinstance(new_givencondition, RandomSymbol):
            condrv = random_symbols(new_condition)
            if len(condrv) == 1 and condrv[0] == new_givencondition:
                return BernoulliDistribution(self.probability(new_condition),
                                             0, 1)

            if any([dependent(rv, new_givencondition) for rv in condrv]):
                return Probability(new_condition, new_givencondition)
            else:
                return self.probability(new_condition)

        if new_givencondition is not None and \
                not isinstance(new_givencondition, (Relational, Boolean)):
            raise ValueError(
                "%s is not a relational or combination of relationals" %
                (new_givencondition))
        if new_givencondition == False:
            return S.Zero
        if new_condition == True:
            return S.One
        if new_condition == False:
            return S.Zero
        if not isinstance(new_condition, (Relational, Boolean)):
            raise ValueError(
                "%s is not a relational or combination of relationals" %
                (new_condition))
        if new_givencondition is not None:  # If there is a condition
            # Recompute on new conditional expr
            return self.probability(
                given(new_condition, new_givencondition, **kwargs), **kwargs)
        return pspace(new_condition).probability(new_condition, **kwargs)
예제 #4
0
    def doit(self, **hints):
        deep = hints.get('deep', True)
        condition = self._condition
        expr = self.args[0]
        numsamples = hints.get('numsamples', False)
        for_rewrite = not hints.get('for_rewrite', False)

        if deep:
            expr = expr.doit(**hints)

        if not is_random(expr) or isinstance(
                expr, Expectation):  # expr isn't random?
            return expr
        if numsamples:  # Computing by monte carlo sampling?
            evalf = hints.get('evalf', True)
            return sampling_E(expr,
                              condition,
                              numsamples=numsamples,
                              evalf=evalf)

        if expr.has(RandomIndexedSymbol):
            return pspace(expr).compute_expectation(expr, condition)

        # Create new expr and recompute E
        if condition is not None:  # If there is a condition
            return self.func(given(expr, condition)).doit(**hints)

        # A few known statements for efficiency

        if expr.is_Add:  # We know that E is Linear
            return Add(*[
                self.func(arg, condition).doit(
                    **hints) if not isinstance(arg, Expectation) else self.
                func(arg, condition) for arg in expr.args
            ])
        if expr.is_Mul:
            if expr.atoms(Expectation):
                return expr

        if pspace(expr) == PSpace():
            return self.func(expr)
        # Otherwise case is simple, pass work off to the ProbabilitySpace
        result = pspace(expr).compute_expectation(expr, evaluate=for_rewrite)
        if hasattr(result, 'doit') and for_rewrite:
            return result.doit(**hints)
        else:
            return result
예제 #5
0
 def __new__(cls, *prob, given=None):
     booleans = []
     for arg in prob:
         assert arg.is_random
         if arg.is_symbol:
             booleans.append(Equality(arg, pspace(arg).symbol))
         elif arg.is_Conditioned:
             lhs, rhs = arg.args
             if lhs.is_symbol:
                 booleans.append(
                     arg.func(Equality(lhs,
                                       pspace(lhs).symbol), rhs))
             else:
                 booleans.append(arg)
         else:
             assert arg.is_Boolean, type(arg)
             booleans.append(arg)
     expr = And(*booleans)
     if given is not None:
         expr = rv.given(expr, given)
     obj = Expr.__new__(cls, expr)
     return obj
예제 #6
0
 def doit(self, **hints):
     return given(self.lhs, self.rhs)