def _rvindexed_subs(self, expr, condition=None):
        """
        Substitutes the RandomIndexedSymbol with the RandomSymbol with
        same name, distribution and probability as RandomIndexedSymbol.

        """

        rvs_expr = random_symbols(expr)
        if len(rvs_expr) != 0:
            swapdict_expr = {}
            for rv in rvs_expr:
                if isinstance(rv, RandomIndexedSymbol):
                    newrv = Bernoulli(rv.name,
                                      p=rv.pspace.process.p,
                                      succ=self.success,
                                      fail=self.failure)
                    swapdict_expr[rv] = newrv
            expr = expr.subs(swapdict_expr)
        rvs_cond = random_symbols(condition)
        if len(rvs_cond) != 0:
            swapdict_cond = {}
            if condition is not None:
                for rv in rvs_cond:
                    if isinstance(rv, RandomIndexedSymbol):
                        newrv = Bernoulli(rv.name,
                                          p=rv.pspace.process.p,
                                          succ=self.success,
                                          fail=self.failure)
                        swapdict_cond[rv] = newrv
                condition = condition.subs(swapdict_cond)
        return expr, condition
Exemple #2
0
 def set(self):
     rvs = [i for i in random_symbols(self.args[1])]
     marginalise_out = [i for i in random_symbols(self.args[1]) \
      if i not in self.args[1]]
     for i in rvs:
         if i in marginalise_out:
             rvs.remove(i)
     return ProductSet((i.pspace.set for i in rvs))
Exemple #3
0
 def pdf(self, x):
     dist = self.args[0]
     randoms = []
     for arg in dist.args:
         randoms.extend(random_symbols(arg))
     if len(randoms) > 1:
         raise NotImplementedError("Compound Distributions for more than"
             " one random argument is not implemeted yet.")
     rand_sym = randoms[0]
     if isinstance(dist, SingleFiniteDistribution):
         y = Dummy('y', integer=True, negative=False)
         _pdf = dist.pmf(y)
     else:
         y = Dummy('y')
         _pdf = dist.pdf(y)
     if isinstance(rand_sym.pspace.distribution, SingleFiniteDistribution):
         rand_dens = rand_sym.pspace.distribution.pmf(rand_sym)
     else:
         rand_dens = rand_sym.pspace.distribution.pdf(rand_sym)
     rand_sym_dom = rand_sym.pspace.domain.set
     if rand_sym.pspace.is_Discrete or rand_sym.pspace.is_Finite:
         _pdf = Sum(_pdf*rand_dens, (rand_sym, rand_sym_dom._inf,
                 rand_sym_dom._sup)).doit()
     else:
         _pdf = integrate(_pdf*rand_dens, (rand_sym, rand_sym_dom._inf,
                 rand_sym_dom._sup))
     return Lambda(y, _pdf)(x)
Exemple #4
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
Exemple #5
0
 def where(self, condition):
     rvs = frozenset(random_symbols(condition))
     if not (len(rvs) == 1 and rvs.issubset(self.values)):
         raise NotImplementedError("Multiple continuous random variables not supported")
     rv = tuple(rvs)[0]
     interval = reduce_rational_inequalities_wrap(condition, rv)
     interval = interval.intersect(self.domain.set)
     return SingleContinuousDomain(rv.symbol, interval)
    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)
Exemple #7
0
 def __new__(cls,dist, rvs):
     if not all([isinstance(rv, (Indexed, RandomSymbol))] for rv in rvs):
         raise ValueError(filldedent('''Marginal distribution can be
          intitialised only in terms of random variables or indexed random
          variables'''))
     rvs = Tuple.fromiter(rv for rv in rvs)
     if not isinstance(dist, JointDistribution) and len(random_symbols(dist)) == 0:
         return dist
     return Basic.__new__(cls, dist, rvs)
Exemple #8
0
 def where(self, condition):
     rvs = frozenset(random_symbols(condition))
     if not (len(rvs) == 1 and rvs.issubset(self.values)):
         raise NotImplementedError(
             "Multiple continuous random variables not supported")
     rv = tuple(rvs)[0]
     interval = reduce_poly_inequalities_wrap(condition, rv)
     interval = interval.intersect(self.domain.set)
     return SingleContinuousDomain(rv.symbol, interval)
Exemple #9
0
 def where(self, condition):
     rvs = random_symbols(condition)
     assert all(r.symbol in self.symbols for r in rvs)
     if (len(rvs) > 1):
         raise NotImplementedError(filldedent('''Multivariate discrete
         random variables are not yet supported.'''))
     conditional_domain = reduce_rational_inequalities_wrap(condition,
         rvs[0])
     conditional_domain = conditional_domain.intersect(self.domain.set)
     return SingleDiscreteDomain(rvs[0].symbol, conditional_domain)
Exemple #10
0
 def _compound_check(self, dist):
     """
     Checks if the given distribution contains random parameters.
     """
     randoms = []
     for arg in dist.args:
         randoms.extend(random_symbols(arg))
     if len(randoms) == 0:
         return False
     return True
Exemple #11
0
 def restricted_domain(self, condition):
     rvs = random_symbols(condition)
     assert all(r.symbol in self.symbols for r in rvs)
     if (len(rvs) > 1):
         raise NotImplementedError(filldedent('''Multivariate discrete
         random variables are not yet supported.'''))
     conditional_domain = reduce_rational_inequalities_wrap(condition,
         rvs[0])
     conditional_domain = conditional_domain.intersect(self.domain.set)
     return conditional_domain
Exemple #12
0
 def compute_density(self, expr):
     if self._is_symbolic:
         rv = list(random_symbols(expr))[0]
         k = Dummy('k', integer=True)
         cond = True if not isinstance(expr, (Relational, Logic)) \
                  else expr.subs(rv, k)
         return Lambda(k,
         Piecewise((self.pmf(k), And(k >= self.args[1].low,
         k <= self.args[1].high, cond)), (0, True)))
     expr = rv_subs(expr, self.values)
     return FinitePSpace(self.domain, self.distribution).compute_density(expr)
Exemple #13
0
 def pdf(self, *x):
     expr, rvs = self.args[0], self.args[1]
     marginalise_out = [i for i in random_symbols(expr) if i not in rvs]
     if isinstance(expr, JointDistribution):
         count = len(expr.domain.args)
         x = Dummy('x', real=True, finite=True)
         syms = tuple(Indexed(x, i) for i in count)
         expr = expr.pdf(syms)
     else:
         syms = tuple(rv.pspace.symbol if isinstance(rv, RandomSymbol) else rv.args[0] for rv in rvs)
     return Lambda(syms, self.compute_pdf(expr, marginalise_out))(*x)
Exemple #14
0
 def compute_expectation(self, expr, rvs=None, **kwargs):
     if self._is_symbolic:
         rv = random_symbols(expr)[0]
         k = Dummy('k', integer=True)
         expr = expr.subs(rv, k)
         cond = True if not isinstance(expr, (Relational, Logic)) \
                 else expr
         func = self.pmf(k) * k if cond != True else self.pmf(k) * expr
         return Sum(Piecewise((func, cond), (0, True)),
             (k, self.distribution.low, self.distribution.high)).doit()
     expr = rv_subs(expr, rvs)
     return FinitePSpace(self.domain, self.distribution).compute_expectation(expr, rvs, **kwargs)
Exemple #15
0
 def probability(self, condition):
     cond_symbols = frozenset(rs.symbol for rs in random_symbols(condition))
     cond = rv_subs(condition)
     if not cond_symbols.issubset(self.symbols):
         raise ValueError("Cannot compare foreign random symbols, %s"
                          %(str(cond_symbols - self.symbols)))
     if isinstance(condition, Relational) and \
         (not cond.free_symbols.issubset(self.domain.free_symbols)):
         rv = condition.lhs if isinstance(condition.rhs, Symbol) else condition.rhs
         return sum(Piecewise(
                    (self.prob_of(elem), condition.subs(rv, list(elem)[0][1])),
                    (0, True)) for elem in self.domain)
     return sum(self.prob_of(elem) for elem in self.where(condition))
Exemple #16
0
def JointRV(symbol, pdf, _set=None):
    """
    Create a Joint Random Variable where each of its component is continuous,
    given the following:

    Parameters
    ==========

    symbol : Symbol
        Represents name of the random variable.
    pdf : A PDF in terms of indexed symbols of the symbol given
        as the first argument

    NOTE
    ====

    As of now, the set for each component for a ``JointRV`` is
    equal to the set of all integers, which cannot be changed.

    Examples
    ========

    >>> from sympy import exp, pi, Indexed, S
    >>> from sympy.stats import density, JointRV
    >>> x1, x2 = (Indexed('x', i) for i in (1, 2))
    >>> pdf = exp(-x1**2/2 + x1 - x2**2/2 - S(1)/2)/(2*pi)
    >>> N1 = JointRV('x', pdf) #Multivariate Normal distribution
    >>> density(N1)(1, 2)
    exp(-2)/(2*pi)

    Returns
    =======

    RandomSymbol

    """
    #TODO: Add support for sets provided by the user
    symbol = sympify(symbol)
    syms = list(i for i in pdf.free_symbols if isinstance(i, Indexed)
        and i.base == IndexedBase(symbol))
    syms = tuple(sorted(syms, key = lambda index: index.args[1]))
    _set = S.Reals**len(syms)
    pdf = Lambda(syms, pdf)
    dist = JointDistributionHandmade(pdf, _set)
    jrv = JointPSpace(symbol, dist).value
    rvs = random_symbols(pdf)
    if len(rvs) != 0:
        dist = MarginalDistribution(dist, (jrv,))
        return JointPSpace(symbol, dist).value
    return jrv
    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 random_symbols(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
Exemple #18
0
 def pdf(self, *x):
     expr, rvs = self.args[0], self.args[1]
     marginalise_out = [i for i in random_symbols(expr) if i not in self.args[1]]
     syms = [i.pspace.symbol for i in self.args[1]]
     for i in expr.atoms(Indexed):
         if isinstance(i, Indexed) and isinstance(i.base, RandomSymbol)\
          and i not in rvs:
             marginalise_out.append(i)
     if isinstance(expr, CompoundDistribution):
         syms = Dummy('x', real=True)
         expr = expr.args[0].pdf(syms)
     elif isinstance(expr, JointDistribution):
         count = len(expr.domain.args)
         x = Dummy('x', real=True, finite=True)
         syms = [Indexed(x, i) for i in count]
         expr = expression.pdf(syms)
     return Lambda(syms, self.compute_pdf(expr, marginalise_out))(*x)
Exemple #19
0
 def compute_expectation(self, expr, rvs=None, evaluate=False, **kwargs):
     syms = tuple(self.value[i] for i in range(self.component_count))
     rvs = rvs or syms
     if not any([i in rvs for i in syms]):
         return expr
     expr = expr*self.pdf
     for rv in rvs:
         if isinstance(rv, Indexed):
             expr = expr.xreplace({rv: Indexed(str(rv.base), rv.args[1])})
         elif isinstance(rv, RandomSymbol):
             expr = expr.xreplace({rv: rv.symbol})
     if self.value in random_symbols(expr):
         raise NotImplementedError(filldedent('''
         Expectations of expression with unindexed joint random symbols
         cannot be calculated yet.'''))
     limits = tuple((Indexed(str(rv.base),rv.args[1]),
         self.distribution.set.args[rv.args[1]]) for rv in syms)
     return Integral(expr, *limits)
Exemple #20
0
 def compute_expectation(self, expr, rvs=None, evaluate=False, **kwargs):
     syms = tuple(self.value[i] for i in range(self.component_count))
     rvs = rvs or syms
     if not any([i in rvs for i in syms]):
         return expr
     expr = expr*self.pdf
     for rv in rvs:
         if isinstance(rv, Indexed):
             expr = expr.xreplace({rv: Indexed(str(rv.base), rv.args[1])})
         elif isinstance(rv, RandomSymbol):
             expr = expr.xreplace({rv: rv.symbol})
     if self.value in random_symbols(expr):
         raise NotImplementedError(filldedent('''
         Expectations of expression with unindexed joint random symbols
         cannot be calculated yet.'''))
     limits = tuple((Indexed(str(rv.base),rv.args[1]),
         self.distribution.set.args[rv.args[1]]) for rv in syms)
     return Integral(expr, *limits)
Exemple #21
0
def JointRV(symbol, pdf, _set=None):
    """
    Create a Joint Random Variable where each of its component is conitinuous,
    given the following:

    -- a symbol
    -- a PDF in terms of indexed symbols of the symbol given
     as the first argument

    NOTE: As of now, the set for each component for a `JointRV` is
    equal to the set of all integers, which can not be changed.

    Returns a RandomSymbol.

    Examples
    ========

    >>> from sympy import symbols, exp, pi, Indexed, S
    >>> from sympy.stats import density
    >>> from sympy.stats.joint_rv_types import JointRV

    >>> x1, x2 = (Indexed('x', i) for i in (1, 2))
    >>> pdf = exp(-x1**2/2 + x1 - x2**2/2 - S(1)/2)/(2*pi)

    >>> N1 = JointRV('x', pdf) #Multivariate Normal distribution
    >>> density(N1)(1, 2)
    exp(-2)/(2*pi)
    """
    #TODO: Add support for sets provided by the user
    symbol = sympify(symbol)
    syms = list(i for i in pdf.free_symbols if isinstance(i, Indexed)
        and i.base == IndexedBase(symbol))
    syms.sort(key = lambda index: index.args[1])
    _set = S.Reals**len(syms)
    pdf = Lambda(syms, pdf)
    dist = JointDistributionHandmade(pdf, _set)
    jrv = JointPSpace(symbol, dist).value
    rvs = random_symbols(pdf)
    if len(rvs) != 0:
        dist = MarginalDistribution(dist, (jrv,))
        return JointPSpace(symbol, dist).value
    return jrv
Exemple #22
0
    def probability(self, condition, **kwargs):
        z = Dummy('z', real=True)
        cond_inv = False
        if isinstance(condition, Ne):
            condition = Eq(condition.args[0], condition.args[1])
            cond_inv = True
        # Univariate case can be handled by where
        try:
            domain = self.where(condition)
            rv = [rv for rv in self.values if rv.symbol == domain.symbol][0]
            # Integrate out all other random variables
            pdf = self.compute_density(rv, **kwargs)
            # return S.Zero if `domain` is empty set
            if domain.set is S.EmptySet or isinstance(domain.set, FiniteSet):
                return S.Zero if not cond_inv else S.One
            if isinstance(domain.set, Union):
                return sum(
                    Integral(pdf(z), (z, subset), **kwargs)
                    for subset in domain.set.args
                    if isinstance(subset, Interval))
            # Integrate out the last variable over the special domain
            return Integral(pdf(z), (z, domain.set), **kwargs)

        # Other cases can be turned into univariate case
        # by computing a density handled by density computation
        except NotImplementedError:
            from sympy.stats.rv import density
            expr = condition.lhs - condition.rhs
            if not random_symbols(expr):
                dens = self.density
                comp = condition.rhs
            else:
                dens = density(expr, **kwargs)
                comp = 0
            if not isinstance(dens, ContinuousDistribution):
                from sympy.stats.crv_types import ContinuousDistributionHandmade
                dens = ContinuousDistributionHandmade(dens,
                                                      set=self.domain.set)
            # Turn problem into univariate case
            space = SingleContinuousPSpace(z, dens)
            result = space.probability(condition.__class__(space.value, comp))
            return result if not cond_inv else S.One - result
Exemple #23
0
 def probability(self, condition):
     cond_symbols = frozenset(rs.symbol for rs in random_symbols(condition))
     assert cond_symbols.issubset(self.symbols)
     return sum(self.prob_of(elem) for elem in self.where(condition))
Exemple #24
0
 def where(self, condition):
     assert all(r.symbol in self.symbols for r in random_symbols(condition))
     return ConditionalFiniteDomain(self.domain, condition)
Exemple #25
0
 def where(self, condition):
     assert all(r.symbol in self.symbols for r in random_symbols(condition))
     return ConditionalFiniteDomain(self.domain, condition)
Exemple #26
0
 def domain(self):
     rvs = random_symbols(self.distribution)
     if not rvs:
         return SingleDomain(self.symbol, self.distribution.set)
     return ProductDomain(*[rv.pspace.domain for rv in rvs])
Exemple #27
0
 def latent_distributions(self):
     return random_symbols(self.args[0])
Exemple #28
0
 def probability(self, condition):
     cond_symbols = frozenset(rs.symbol for rs in random_symbols(condition))
     assert cond_symbols.issubset(self.symbols)
     return sum(self.prob_of(elem) for elem in self.where(condition))
    def expectation(self, expr, condition=None, evaluate=True, **kwargs):
        """
        Handles expectation queries for markov process.

        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
            Unevaluated object if computations cannot be done due to
            insufficient information.
        Expr
            In all other cases when the computations are successful.

        Note
        ====

        Any information passed at the time of query overrides
        any information passed at the time of object creation like
        transition probabilities, state space.

        Pass the transition matrix using TransitionMatrixOf,
        generator matrix using GeneratorMatrixOf and state space
        using StochasticStateSpaceOf in given_condition using & or And.
        """

        check, mat, state_space, condition = \
            self._preprocess(condition, evaluate)

        if check:
            return Expectation(expr, condition)

        rvs = random_symbols(expr)
        if isinstance(expr, Expr) and isinstance(condition, Eq) \
            and len(rvs) == 1:
            # handle queries similar to E(f(X[i]), Eq(X[i-m], <some-state>))
            rv = list(rvs)[0]
            lhsg, rhsg = condition.lhs, condition.rhs
            if not isinstance(lhsg, RandomIndexedSymbol):
                lhsg, rhsg = (rhsg, lhsg)
            if rhsg not in self.state_space:
                raise ValueError("%s state is not in the state space." %
                                 (rhsg))
            if rv.key < lhsg.key:
                raise ValueError(
                    "Incorrect given condition is given, expectation "
                    "time %s < time %s" % (rv.key, rv.key))
            mat_of = TransitionMatrixOf(self, mat) if isinstance(
                self, DiscreteMarkovChain) else GeneratorMatrixOf(self, mat)
            cond = condition & mat_of & \
                    StochasticStateSpaceOf(self, state_space)
            func = lambda s: self.probability(Eq(rv, s), cond) * expr.subs(
                rv, s)
            return sum([func(s) for s in state_space])

        raise NotImplementedError(
            "Mechanism for handling (%s, %s) queries hasn't been "
            "implemented yet." % (expr, condition))
Exemple #30
0
 def domain(self):
     rvs = random_symbols(self.distribution)
     if len(rvs) == 0:
         return SingleDomain(self.symbol, self.set)
     return ProductDomain(*[rv.pspace.domain for rv in rvs])