def prove(Eq): x = Symbol.x(real=True, random=True) y = Symbol.y(real=True, random=True) z = Symbol.z(real=True, random=True) Eq << apply(Equality(x | y.as_boolean() & z.as_boolean(), x)) Eq << Eq[0].domain_definition() Eq.y_nonzero, Eq.z_nonzero = bayes.inequality.et.apply(Eq[-1]).split() Eq.xy_probability = bayes.theorem.apply(Eq.y_nonzero, var=x) Eq << bayes.theorem.apply(Eq[2], var=x) Eq << Eq[-1].subs(Eq[0]) Eq <<= Eq[-1].lhs.total_probability_theorem( z), Eq[-1].rhs.args[0].total_probability_theorem(z), Eq[-1].integral( (pspace(z).symbol, )) Eq << Eq[-3].subs(Eq.xy_probability) Eq << Eq[-1].subs(Eq[-2]) Eq << Eq[-1].subs(Eq[-4]) Eq << algebre.scalar.inequality.equality.apply(Eq[-1], Eq.y_nonzero) Eq << Eq[-1].reversed
def test_density(): x = Symbol('x') l = Symbol('l', positive=True) rate = Beta(l, 2, 3) X = Poisson(x, rate) assert isinstance(pspace(X), ProductPSpace) assert density(X, Eq(rate, rate.symbol)) == PoissonDistribution(l)
def apply(*given): x, y = process_assumptions(*given) n, d = x.shape t = Symbol.t(integer=True, domain=[0, n - 1]) i = Symbol.i(integer=True) joint_probability = P(x[:t + 1], y[:t + 1]) emission_probability = P(x[i] | y[i]) transition_probability = P(y[i] | y[i - 1]) y_given_x_probability = P(y | x) y = pspace(y).symbol G = Symbol.G(shape=(d, d), definition=LAMBDA[y[i - 1], y[i]](-sympy.log(transition_probability))) s = Symbol.s(shape=(n, ), definition=LAMBDA[t](-log(joint_probability))) x = Symbol.x(shape=(n, d), definition=LAMBDA[y[i], i](-sympy.log(emission_probability))) z = Symbol.z(shape=(n, d), definition=LAMBDA[y[t], t](Piecewise( (Sum[y[0:t]](sympy.E**-s[t]), t > 0), (sympy.E**-s[t], True)))) # assert z.is_extended_positive x_quote = Symbol.x_quote(shape=(n, d), definition=-LAMBDA[t](sympy.log(z[t]))) # assert x_quote.is_real return Equality(x_quote[t + 1], -log(Sum(exp(-x_quote[t] - G))) + x[t + 1], given=given), \ Equality(-log(y_given_x_probability), log(Sum(exp(-x_quote[n - 1]))) + s[n - 1], given=given)
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)
def apply(*given): x, y = process_assumptions(*given) n, d = x.shape t = Symbol.t(integer=True, domain=[0, n - 1]) i = Symbol.i(integer=True) joint_probability_t = P(x[:t + 1], y[:t + 1]) joint_probability = P(x, y) emission_probability = P(x[i] | y[i]) transition_probability = P(y[i] | y[i - 1]) y = pspace(y).symbol G = Symbol.G(shape=(d, d), definition=LAMBDA[y[i - 1], y[i]](-sympy.log(transition_probability))) s = Symbol.s(shape=(n, ), definition=LAMBDA[t](-log(joint_probability_t))) x = Symbol.x(shape=(n, d), definition=LAMBDA[y[i], i](-sympy.log(emission_probability))) x_quote = Symbol.x_quote(shape=(n, d), definition=LAMBDA[y[t], t](Piecewise( (MIN[y[0:t]](s[t]), t > 0), (s[0], True)))) assert x_quote.is_real return Equality(x_quote[t + 1], x[t + 1] + MIN(x_quote[t] + G), given=given), \ Equality(MAX[y](joint_probability), exp(-MIN(x_quote[n - 1])), given=given)
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
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)
def apply(x0, x1): assert x0.is_random and x1.is_random pspace0 = pspace(x0) pspace1 = pspace(x1) if not isinstance(pspace0, SingleDiscretePSpace) or not isinstance( pspace1, SingleDiscretePSpace): return None distribution0 = pspace0.distribution distribution1 = pspace1.distribution if not isinstance(distribution0, PoissonDistribution) or not isinstance( distribution1, PoissonDistribution): return None Y = Symbol.y(distribution=PoissonDistribution(distribution0.lamda + distribution1.lamda)) y = pspace(Y).symbol return Equality(PDF(x0 + x1)(y), PDF(Y)(y).doit())
def prove(Eq): # d is the number of output labels # oo is the length of the sequence d = Symbol.d(integer=True, positive=True) n = Symbol.n(integer=True, positive=True) x = Symbol.x(shape=(n, d), real=True, random=True, given=True) y = Symbol.y(shape=(n, ), integer=True, domain=[0, d - 1], random=True, given=True) i = Symbol.i(integer=True) t = Symbol.t(integer=True, domain=[0, n]) joint_probability_t = P(x[:t + 1], y[:t + 1]) emission_probability = P(x[i] | y[i]) transition_probability = P(y[i] | y[i - 1]) given = Equality( joint_probability_t, P(x[0] | y[0]) * P(y[0]) * Product[i:1:t](transition_probability * emission_probability)) y = pspace(y).symbol G = Symbol.G(shape=(d, d), definition=LAMBDA[y[i - 1], y[i]](-sympy.log(transition_probability))) s = Symbol.s(shape=(n, ), definition=LAMBDA[t](-log(joint_probability_t))) x = Symbol.x(shape=(n, d), definition=LAMBDA[y[i], i](-sympy.log(emission_probability))) Eq.s_definition, Eq.G_definition, Eq.x_definition, Eq.given, Eq.logits_recursion = apply( G, x, s, given=given) Eq << Eq.s_definition.this.rhs.subs(Eq.given) Eq << Eq[-1].this.rhs.args[1].as_Add() Eq << Eq[-1].subs(Eq.x_definition.subs(i, 0).reversed) Eq << Eq[-1].this.rhs.args[-1].args[1].as_Add() Eq << Eq[-1].this.rhs.args[-1].args[1].function.as_Add() Eq << Eq[-1].this.rhs.args[-1].args[1].as_two_terms() Eq << Eq[-1].subs(Eq.x_definition.reversed).subs(Eq.G_definition.reversed) Eq << Eq[-1].this.rhs.args[-1].bisect({0}) Eq << Eq[-1].subs(t, t + 1) - Eq[-1] s = Eq.s_definition.lhs.base Eq << Eq[-1].this.rhs.simplify() + s[t]
def apply(x0, x1): assert x0.is_random and x1.is_random pspace0 = pspace(x0) pspace1 = pspace(x1) if not isinstance(pspace0, SingleContinuousPSpace) or not isinstance( pspace1, SingleContinuousPSpace): return None distribution0 = pspace0.distribution distribution1 = pspace1.distribution if not isinstance(distribution0, NormalDistribution) or not isinstance( distribution1, NormalDistribution): return None Y = Symbol.y(distribution=NormalDistribution( distribution0.mean + distribution1.mean, sqrt(distribution0.std * distribution0.std + distribution1.std * distribution1.std))) y = pspace(Y).symbol return Equality(PDF(x0 + x1)(y), PDF(Y)(y).doit())
def apply(given): assert given.is_Unequality assert given.lhs.is_Probability assert given.rhs.is_zero eq = given.lhs.arg x, _x = eq.args assert _x == pspace(x).symbol n = x.shape[0] t = Symbol.t(integer=True, domain=[1, n - 1]) return Unequal(P(x[:t]), 0, given=given)
def test_density(): x = Symbol('x') l = Symbol('l', positive=True) rate = Beta(l, 2, 3) X = Poisson(x, rate) assert isinstance(pspace(X), JointPSpace) assert density(X, Eq(rate, rate.symbol)) == PoissonDistribution(l) N1 = Normal('N1', 0, 1) N2 = Normal('N2', N1, 2) assert density(N2)(0).doit() == sqrt(10) / (10 * sqrt(pi)) assert simplify(density(N2, Eq(N1, 1))(x)) == \ sqrt(2)*exp(-(x - 1)**2/8)/(4*sqrt(pi))
def apply(X, Y): i = Symbol.i(integer=True) assert Y.is_random and X.is_random y = pspace(Y).symbol assert y >= 0 assert not y.is_random assert isinstance(Y.distribution, ChiSquaredDistribution) k = Y.distribution.k assert Sum[i:k](X[i] * X[i]).is_random return Equality(PDF(Sum[i:k](X[i] * X[i]))(y), PDF(Y)(y).doit())
def test_density(): x = Symbol('x') l = Symbol('l', positive=True) rate = Beta(l, 2, 3) X = Poisson(x, rate) assert isinstance(pspace(X), JointPSpace) assert density(X, Eq(rate, rate.symbol)) == PoissonDistribution(l) N1 = Normal('N1', 0, 1) N2 = Normal('N2', N1, 2) assert density(N2)(0).doit() == sqrt(10)/(10*sqrt(pi)) assert simplify(density(N2, Eq(N1, 1))(x)) == \ sqrt(2)*exp(-(x - 1)**2/8)/(4*sqrt(pi))
def apply(given, var): assert given.is_Unequality x_probability, zero = given.args assert zero.is_zero eq = x_probability.arg if eq.is_Equality: x, _x = eq.args assert x.is_random and _x == pspace(x).symbol if var.is_Probability: joint_probability = var marginal_probability = joint_probability.marginalize(x) if marginal_probability is None: var = joint_probability.arg joint_probability = P(joint_probability.arg, x) else: var = marginal_probability.arg assert not var.is_Conditioned return Equality(joint_probability, P(var | x) * P(x), given=given) else: return Equality(P(x, var), P(var | x) * P(x), given=given) elif eq.is_Conditioned: x, _x = eq.lhs.args assert x.is_random and _x == pspace(x).symbol assert var.is_Probability joint_probability = var var = joint_probability.marginalize(x).arg assert var.is_Conditioned assert var.rhs == eq.rhs return Equality(joint_probability, P(var | x) * P(x, given=eq.rhs), given=given) else: assert eq.is_And assert var.is_random and var.is_symbol assert var.as_boolean() not in eq._argset return Equality(P(eq, var), P(var | eq) * P(eq), given=given)
def apply(x0, x1): if not x0.is_random or not x1.is_random: return pspace0 = pspace(x0) pspace1 = pspace(x1) if not isinstance(pspace0, SingleDiscretePSpace) or not isinstance( pspace1, SingleDiscretePSpace): return distribution0 = pspace0.distribution distribution1 = pspace1.distribution if not isinstance(distribution0, BinomialDistribution) or not isinstance( distribution1, BinomialDistribution): return if distribution0.p != distribution1.p: return Y = Symbol.y( distribution=BinomialDistribution(distribution0.n + distribution1.n, distribution0.p)) y = pspace(Y).symbol return Equality(PDF(x0 + x1)(y), PDF(Y)(y).doit())
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
def apply(given, indices): assert given.is_Unequality assert given.lhs.is_Probability assert given.rhs.is_zero eqs = given.lhs.arg assert eqs.is_And args = [] for eq, t in zip(eqs.args, indices): x, _x = eq.args assert _x == pspace(x).symbol args.append(x[t]) return Unequal(P(*args), 0, given=given)
def marginalize_condition(cls, condition, given): if condition.is_And: expr = [] hit = False for eq in condition.args: if eq.is_Equality: lhs, rhs = eq.args if lhs.is_symbol and pspace(lhs).symbol == rhs: if lhs._has(given): if lhs == given: hit = True continue if given.is_Indexed: start = given.indices[0] stop = start + 1 elif given.is_Slice: start, stop = given.indices else: expr.append(eq) continue lhs = lhs.bisect(Slice[start:stop]) if not lhs.is_Concatenate: hit = True else: rhs = rhs.bisect(Slice[start:stop]) for lhs, rhs in zip(lhs.args, rhs.args): eq = Equality(lhs, rhs) if lhs == given: hit = True else: expr.append(eq) continue expr.append(eq) if hit: return cls(And(*expr)) elif condition.is_Conditioned: self = cls(condition.lhs).marginalize(given) return self.func(self.arg, given=condition.rhs) elif condition.is_Equal: if given.is_Slice: start, stop = given.indices condition = condition.bisect(Slice[start:stop]) elif given.is_Indexed: condition = condition.bisect(Slice[given.indices]) if condition.is_And: return cls.marginalize_condition(condition, given)
def prove(Eq): x = Symbol.x(real=True, random=True) y = Symbol.y(real=True, random=True) z = Symbol.z(real=True, random=True) w = Symbol.w(real=True, random=True) Eq << apply(Equality(x | y.as_boolean() & z.as_boolean() & w.as_boolean(), x | w), wrt=y) Eq.xyz_nonzero, Eq.w_nonzero = Eq[0].domain_definition().split() _, Eq.y_nonzero, Eq.z_nonzero = bayes.inequality.et.apply( Eq.xyz_nonzero).split() Eq.xy_probability = bayes.theorem.apply(Eq.y_nonzero, var=x | w) Eq << bayes.inequality.inequality.conditioned.apply(Eq.xyz_nonzero, wrt=w) Eq << P(x | w, y, z).bayes_theorem(y, z) Eq << Eq[-1].as_Or() Eq << (Eq[-1] & Eq[-3]).split() Eq << Eq[-1].subs(Eq[0]) Eq <<= Eq[-1].lhs.total_probability_theorem( z), Eq[-1].rhs.args[0].total_probability_theorem(z), Eq[-1].integral( (pspace(z).symbol, )) Eq << Eq[-3].subs(Eq.xy_probability) Eq << Eq[-1].subs(Eq[-2]) Eq << Eq[-1].subs(Eq[-4]) Eq << algebre.scalar.inequality.equality.apply(Eq[-1], Eq.y_nonzero) Eq << Eq[-1].reversed
def prove(Eq): x = Symbol.x(real=True, random=True) y = Symbol.y(real=True, random=True) z = Symbol.z(real=True, random=True) Eq << apply(Equality(x | y.as_boolean() & z.as_boolean(), x | y), Equality(z | y, z)) Eq.yz_nonzero, Eq.y_nonzero = Eq[0].domain_definition().split() _, Eq.z_nonzero = bayes.inequality.et.apply(Eq.yz_nonzero).split() Eq << bayes.theorem.apply(Eq.yz_nonzero, var=x) Eq << Eq[-1].subs(Eq[0]) Eq << bayes.theorem.apply(Eq.y_nonzero, var=z) Eq << Eq[-2].subs(Eq[-1]) Eq.xy_probability = bayes.theorem.apply(Eq.y_nonzero, var=x) Eq << Eq[-1].subs(Eq.xy_probability.reversed) Eq << Eq[-1].subs(Eq[1]) Eq << Eq[-1].lhs.total_probability_theorem(y).subs( bayes.theorem.apply(Eq.z_nonzero, var=x)) Eq << Eq[-2].integrate((pspace(y).symbol, )).subs(Eq[-1]) Eq << Eq.xy_probability.lhs.total_probability_theorem(y) Eq << Eq[-2].subs(Eq[-1]) Eq << algebre.scalar.inequality.equality.apply(Eq[-1], Eq.z_nonzero)
def test_compound_distribution(): Y = Poisson('Y', 1) Z = Poisson('Z', Y) assert isinstance(pspace(Z), JointPSpace) assert isinstance(pspace(Z).distribution, CompoundDistribution) assert Z.pspace.distribution.pdf(1).doit() == exp(-2)*exp(exp(-1))
def test_compound_distribution(): Y = Poisson('Y', 1) Z = Poisson('Z', Y) assert isinstance(pspace(Z), JointPSpace) assert isinstance(pspace(Z).distribution, CompoundDistribution)