def test_discreteuniform(): # Symbolic a, b, c, t = symbols('a b c t') X = DiscreteUniform('X', [a, b, c]) assert E(X) == (a + b + c)/3 assert simplify(variance(X) - ((a**2 + b**2 + c**2)/3 - (a/3 + b/3 + c/3)**2)) == 0 assert P(Eq(X, a)) == P(Eq(X, b)) == P(Eq(X, c)) == S('1/3') Y = DiscreteUniform('Y', range(-5, 5)) # Numeric assert E(Y) == S('-1/2') assert variance(Y) == S('33/4') for x in range(-5, 5): assert P(Eq(Y, x)) == S('1/10') assert P(Y <= x) == S(x + 6)/10 assert P(Y >= x) == S(5 - x)/10 assert dict(density(Die('D', 6)).items()) == \ dict(density(DiscreteUniform('U', range(1, 7))).items()) assert characteristic_function(X)(t) == exp(I*a*t)/3 + exp(I*b*t)/3 + exp(I*c*t)/3 assert moment_generating_function(X)(t) == exp(a*t)/3 + exp(b*t)/3 + exp(c*t)/3
def test_ContinuousRV(): x = Symbol('x') pdf = sqrt(2)*exp(-x**2/2)/(2*sqrt(pi)) # Normal distribution # X and Y should be equivalent X = ContinuousRV(x, pdf) Y = Normal('y', 0, 1) assert variance(X) == variance(Y) assert P(X > 0) == P(Y > 0)
def test_multiple_normal(): X, Y = Normal('x', 0, 1), Normal('y', 0, 1) assert E(X + Y) == 0 assert variance(X + Y) == 2 assert variance(X + X) == 4 assert covariance(X, Y) == 0 assert covariance(2*X + Y, -X) == -2*variance(X) assert E(X, Eq(X + Y, 0)) == 0 assert variance(X, Eq(X + Y, 0)) == S.Half
def test_literal_probability(): X = Normal('X', 2, 3) Y = Normal('Y', 3, 4) Z = Poisson('Z', 4) W = Poisson('W', 3) x, y, w, z = symbols('x, y, w, z') assert Probability(X > 0).doit() == probability(X > 0) assert Probability(X > x).doit() == probability(X > x) assert Expectation(X).doit() == expectation(X) assert Expectation(X**2).doit() == expectation(X**2) assert Expectation(x*X) == x*Expectation(X) assert Expectation(2*X + 3*Y + z*X*Y) == 2*Expectation(X) + 3*Expectation(Y) + z*Expectation(X*Y) assert Expectation(2*X + 3*Y + z*X*Y, evaluate=False).args == (2*X + 3*Y + z*X*Y,) assert Expectation(sin(X)) == Expectation(sin(X), evaluate=False) assert Expectation(2*x*sin(X)*Y + y*X**2 + z*X*Y) == 2*x*Expectation(sin(X)*Y) + y*Expectation(X**2) + z*Expectation(X*Y) assert Variance(w) == 0 assert Variance(X).doit() == variance(X) assert Variance(X + z) == Variance(X) assert Variance(X*Y).args == (Mul(X, Y),) assert type(Variance(X*Y)) == Variance assert Variance(z*X) == z**2*Variance(X) assert Variance(X + Y) == Variance(X) + Variance(Y) + 2*Covariance(X, Y) assert Variance(X + Y + Z + W) == (Variance(X) + Variance(Y) + Variance(Z) + Variance(W) + 2 * Covariance(X, Y) + 2 * Covariance(X, Z) + 2 * Covariance(X, W) + 2 * Covariance(Y, Z) + 2 * Covariance(Y, W) + 2 * Covariance(W, Z)) assert Variance(X**2).doit() == variance(X**2) assert Variance(X**2, evaluate=False) == Variance(X**2) assert Variance(x*X**2) == x**2*Variance(X**2) assert Variance(sin(X)).args == (sin(X),) assert Variance(sin(X), evaluate=False) == Variance(sin(X)) assert Variance(x*sin(X)) == x**2*Variance(sin(X)) assert Covariance(w, z) == 0 assert Covariance(X, w) == 0 assert Covariance(w, X) == 0 assert Covariance(X, Y).args == (X, Y) assert type(Covariance(X, Y)) == Covariance assert Covariance(z*X + 3, Y) == z*Covariance(X, Y) assert Covariance(X, X) == Variance(X) assert Covariance(z*X + 3, w*Y + 4) == w*z*Covariance(X,Y) assert Covariance(X, Y) == Covariance(Y, X) assert Covariance(X + Y, Z + W) == Covariance(W, X) + Covariance(W, Y) + Covariance(X, Z) + Covariance(Y, Z) assert Covariance(x*X + y*Y, z*Z + w*W) == (x*w*Covariance(W, X) + w*y*Covariance(W, Y) + x*z*Covariance(X, Z) + y*z*Covariance(Y, Z)) assert Covariance(x*X**2 + y*sin(Y), z*Y*Z**2 + w*W) == (w*x*Covariance(W, X**2) + w*y*Covariance(sin(Y), W) + x*z*Covariance(Y*Z**2, X**2) + y*z*Covariance(Y*Z**2, sin(Y))) assert Covariance(X, X**2) == Covariance(X, X**2, evaluate=False) assert Covariance(X, sin(X)) == Covariance(sin(X), X, evaluate=False) assert Covariance(X**2, sin(X)*Y) == Covariance(sin(X)*Y, X**2, evaluate=False)
def test_bernoulli(): p, a, b = symbols("p a b") X = Bernoulli(p, a, b, symbol="B") assert E(X) == a * p + b * (-p + 1) assert density(X)[a] == p assert density(X)[b] == 1 - p X = Bernoulli(p, 1, 0, symbol="B") assert E(X) == p assert variance(X) == -p ** 2 + p E(a * X + b) == a * E(X) + b variance(a * X + b) == a ** 2 * variance(X)
def test_bernoulli(): p, a, b = symbols('p a b') X = Bernoulli('B', p, a, b) assert E(X) == a*p + b*(-p + 1) assert density(X)[a] == p assert density(X)[b] == 1 - p X = Bernoulli('B', p, 1, 0) assert E(X) == p assert simplify(variance(X)) == p*(1 - p) E(a*X + b) == a*E(X) + b variance(a*X + b) == a**2 * variance(X)
def test_rademacher(): X = Rademacher('X') assert E(X) == 0 assert variance(X) == 1 assert density(X)[-1] == S.Half assert density(X)[1] == S.Half
def test_rayleigh(): sigma = Symbol("sigma", positive=True) X = Rayleigh('x', sigma) assert density(X)(x) == x*exp(-x**2/(2*sigma**2))/sigma**2 assert E(X) == sqrt(2)*sqrt(pi)*sigma/2 assert variance(X) == -pi*sigma**2/2 + 2*sigma**2
def test_pareto_numeric(): xm, beta = 3, 2 alpha = beta + 5 X = Pareto('x', xm, alpha) assert E(X) == alpha*xm/S(alpha - 1) assert variance(X) == xm**2*alpha / S(((alpha - 1)**2*(alpha - 2)))
def test_weibull(): a, b = symbols('a b', positive=True) X = Weibull('x', a, b) assert simplify(E(X)) == simplify(a * gamma(1 + 1/b)) assert simplify(variance(X)) == simplify(a**2 * gamma(1 + 2/b) - E(X)**2) assert simplify(skewness(X)) == (2*gamma(1 + 1/b)**3 - 3*gamma(1 + 1/b)*gamma(1 + 2/b) + gamma(1 + 3/b))/(-gamma(1 + 1/b)**2 + gamma(1 + 2/b))**(S(3)/2)
def test_bernoulli(): p, a, b, t = symbols('p a b t') X = Bernoulli('B', p, a, b) assert E(X) == a*p + b*(-p + 1) assert density(X)[a] == p assert density(X)[b] == 1 - p assert characteristic_function(X)(t) == p * exp(I * a * t) + (-p + 1) * exp(I * b * t) assert moment_generating_function(X)(t) == p * exp(a * t) + (-p + 1) * exp(b * t) X = Bernoulli('B', p, 1, 0) assert E(X) == p assert simplify(variance(X)) == p*(1 - p) assert E(a*X + b) == a*E(X) + b assert simplify(variance(a*X + b)) == simplify(a**2 * variance(X))
def test_Logarithmic(): p = S.One / 2 x = Logarithmic('x', p) assert E(x) == -p / ((1 - p) * log(1 - p)) assert variance(x) == -1/log(2)**2 + 2/log(2) assert E(2*x**2 + 3*x + 4) == 4 + 7 / log(2) assert isinstance(E(x, evaluate=False), Sum)
def test_gamma(): k = Symbol("k", positive=True) theta = Symbol("theta", positive=True) X = Gamma('x', k, theta) assert density(X) == Lambda(_x, _x**(k - 1)*theta**(-k)*exp(-_x/theta)/gamma(k)) assert cdf(X, meijerg=True) == Lambda(_z, Piecewise( (-k*lowergamma(k, 0)/gamma(k + 1) + k*lowergamma(k, _z/theta)/gamma(k + 1), _z >= 0), (0, True))) assert variance(X) == (-theta**2*gamma(k + 1)**2/gamma(k)**2 + theta*theta**(-k)*theta**(k + 1)*gamma(k + 2)/gamma(k)) k, theta = symbols('k theta', real=True, bounded=True, positive=True) X = Gamma('x', k, theta) assert simplify(E(X)) == k*theta # can't get things to simplify on this one so we use subs assert variance(X).subs(k, 5) == (k*theta**2).subs(k, 5)
def test_maxwell(): a = Symbol("a", positive=True) X = Maxwell("x", a) assert density(X)(x) == (sqrt(2) * x ** 2 * exp(-x ** 2 / (2 * a ** 2)) / (sqrt(pi) * a ** 3)) assert E(X) == 2 * sqrt(2) * a / sqrt(pi) assert simplify(variance(X)) == a ** 2 * (-8 + 3 * pi) / pi
def test_weibull_numeric(): # Test for integers and rationals a = 1 bvals = [S.Half, 1, S(3) / 2, 5] for b in bvals: X = Weibull("x", a, b) assert simplify(E(X)) == simplify(a * gamma(1 + 1 / S(b))) assert simplify(variance(X)) == simplify(a ** 2 * gamma(1 + 2 / S(b)) - E(X) ** 2)
def test_rayleigh(): sigma = Symbol("sigma", positive=True) x = Symbol("x") X = Rayleigh(sigma, symbol=x) assert density(X) == Lambda(_x, _x*exp(-_x**2/(2*sigma**2))/sigma**2) assert E(X) == sqrt(2)*sqrt(pi)*sigma/2 assert variance(X) == -pi*sigma**2/2 + 2*sigma**2
def test_Poisson(): l = 3 x = Poisson('x', l) assert E(x) == l assert variance(x) == l assert density(x) == PoissonDistribution(l) assert isinstance(E(x, evaluate=False), Sum) assert isinstance(E(2*x, evaluate=False), Sum)
def test_negative_binomial(): r = 5 p = S(1) / 3 x = NegativeBinomial('x', r, p) assert E(x) == p*r / (1-p) assert variance(x) == p*r / (1-p)**2 assert E(x**5 + 2*x + 3) == S(9207)/4 assert isinstance(E(x, evaluate=False), Sum)
def test_symbolic(): mu1, mu2 = symbols("mu1 mu2", real=True, bounded=True) s1, s2 = symbols("sigma1 sigma2", real=True, bounded=True, positive=True) rate = Symbol("lambda", real=True, positive=True, bounded=True) X = Normal("x", mu1, s1) Y = Normal("y", mu2, s2) Z = Exponential("z", rate) a, b, c = symbols("a b c", real=True, bounded=True) assert E(X) == mu1 assert E(X + Y) == mu1 + mu2 assert E(a * X + b) == a * E(X) + b assert variance(X) == s1 ** 2 assert simplify(variance(X + a * Y + b)) == variance(X) + a ** 2 * variance(Y) assert E(Z) == 1 / rate assert E(a * Z + b) == a * E(Z) + b assert E(X + a * Z + b) == mu1 + a / rate + b
def test_symbolic(): mu1, mu2 = symbols('mu1 mu2', real=True, finite=True) s1, s2 = symbols('sigma1 sigma2', real=True, finite=True, positive=True) rate = Symbol('lambda', real=True, positive=True, finite=True) X = Normal('x', mu1, s1) Y = Normal('y', mu2, s2) Z = Exponential('z', rate) a, b, c = symbols('a b c', real=True, finite=True) assert E(X) == mu1 assert E(X + Y) == mu1 + mu2 assert E(a*X + b) == a*E(X) + b assert variance(X) == s1**2 assert simplify(variance(X + a*Y + b)) == variance(X) + a**2*variance(Y) assert E(Z) == 1/rate assert E(a*Z + b) == a*E(Z) + b assert E(X + a*Z + b) == mu1 + a/rate + b
def test_Poisson(): l = 3 x = Poisson('x', l) assert E(x) == l assert variance(x) == l assert density(x) == PoissonDistribution(l) assert isinstance(E(x, evaluate=False), Sum) assert isinstance(E(2*x, evaluate=False), Sum) assert characteristic_function(x)(0).doit() == 1
def test_nakagami(): mu = Symbol("mu", positive=True) omega = Symbol("omega", positive=True) X = Nakagami("x", mu, omega) assert density(X)(x) == (2 * x ** (2 * mu - 1) * mu ** mu * omega ** (-mu) * exp(-x ** 2 * mu / omega) / gamma(mu)) assert simplify(E(X, meijerg=True)) == (sqrt(mu) * sqrt(omega) * gamma(mu + S.Half) / gamma(mu + 1)) assert simplify(variance(X, meijerg=True)) == ( omega - omega * gamma(mu + S(1) / 2) ** 2 / (gamma(mu) * gamma(mu + 1)) )
def test_rademacher(): X = Rademacher('X') t = Symbol('t') assert E(X) == 0 assert variance(X) == 1 assert density(X)[-1] == S.Half assert density(X)[1] == S.Half assert characteristic_function(X)(t) == exp(I*t)/2 + exp(-I*t)/2 assert moment_generating_function(X)(t) == exp(t) / 2 + exp(-t) / 2
def test_maxwell(): a = Symbol("a", positive=True) x = Symbol("x") X = Maxwell(a, symbol=x) assert density(X) == (Lambda(_x, sqrt(2)*_x**2*exp(-_x**2/(2*a**2))/ (sqrt(pi)*a**3))) assert E(X) == 2*sqrt(2)*a/sqrt(pi) assert simplify(variance(X)) == a**2*(-8 + 3*pi)/pi
def test_beta(): a, b = symbols('alpha beta', positive=True) B = Beta('x', a, b) assert pspace(B).domain.set == Interval(0, 1) dens = density(B) x = Symbol('x') assert dens(x) == x**(a - 1)*(1 - x)**(b - 1) / beta(a, b) assert simplify(E(B)) == a / (a + b) assert simplify(variance(B)) == a*b / (a**3 + 3*a**2*b + a**2 + 3*a*b**2 + 2*a*b + b**3 + b**2) # Full symbolic solution is too much, test with numeric version a, b = 1, 2 B = Beta('x', a, b) assert expand_func(E(B)) == a / S(a + b) assert expand_func(variance(B)) == (a*b) / S((a + b)**2 * (a + b + 1))
def test_multiple_normal(): X, Y = Normal('x', 0, 1), Normal('y', 0, 1) assert E(X + Y) == 0 assert variance(X + Y) == 2 assert variance(X + X) == 4 assert covariance(X, Y) == 0 assert covariance(2*X + Y, -X) == -2*variance(X) assert skewness(X) == 0 assert skewness(X + Y) == 0 assert correlation(X, Y) == 0 assert correlation(X, X + Y) == correlation(X, X - Y) assert moment(X, 2) == 1 assert cmoment(X, 3) == 0 assert moment(X + Y, 4) == 12 assert cmoment(X, 2) == variance(X) assert smoment(X*X, 2) == 1 assert smoment(X + Y, 3) == skewness(X + Y) assert E(X, Eq(X + Y, 0)) == 0 assert variance(X, Eq(X + Y, 0)) == S.Half
def test_maxwell(): a = Symbol("a", positive=True) X = Maxwell('x', a) assert density(X)(x) == (sqrt(2)*x**2*exp(-x**2/(2*a**2))/ (sqrt(pi)*a**3)) assert E(X) == 2*sqrt(2)*a/sqrt(pi) assert simplify(variance(X)) == a**2*(-8 + 3*pi)/pi assert cdf(X)(x) == erf(sqrt(2)*x/(2*a)) - sqrt(2)*x*exp(-x**2/(2*a**2))/(sqrt(pi)*a) assert diff(cdf(X)(x), x) == density(X)(x)
def test_binomial_symbolic(): n = 10 # Because we're using for loops, can't do symbolic n p = symbols('p', positive=True) X = Binomial('X', n, p) assert simplify(E(X)) == n*p == simplify(moment(X, 1)) assert simplify(variance(X)) == n*p*(1 - p) == simplify(cmoment(X, 2)) assert cancel((skewness(X) - (1-2*p)/sqrt(n*p*(1-p)))) == 0 # Test ability to change success/failure winnings H, T = symbols('H T') Y = Binomial('Y', n, p, succ=H, fail=T) assert simplify(E(Y) - (n*(H*p + T*(1 - p)))) == 0
def test_discreteuniform(): # Symbolic a, b, c = symbols('a b c') X = DiscreteUniform('X', [a,b,c]) assert E(X) == (a+b+c)/3 assert variance(X) == (a**2+b**2+c**2)/3 - (a/3+b/3+c/3)**2 assert P(Eq(X, a)) == P(Eq(X, b)) == P(Eq(X, c)) == S('1/3') Y = DiscreteUniform('Y', range(-5, 5)) # Numeric assert E(Y) == S('-1/2') assert variance(Y) == S('33/4') assert skewness(Y) == 0 for x in range(-5, 5): assert P(Eq(Y, x)) == S('1/10') assert P(Y <= x) == S(x+6)/10 assert P(Y >= x) == S(5-x)/10 assert density(Die('D', 6)) == density(DiscreteUniform('U', range(1,7)))
def test_uniform(): l = Symbol("l", real=True, finite=True) w = Symbol("w", positive=True, finite=True) X = Uniform("x", l, l + w) assert simplify(E(X)) == l + w / 2 assert simplify(variance(X)) == w ** 2 / 12 # With numbers all is well X = Uniform("x", 3, 5) assert P(X < 3) == 0 and P(X > 5) == 0 assert P(X < 4) == P(X > 4) == S.Half
def test_DiscreteMarkovChain(): # pass only the name X = DiscreteMarkovChain("X") assert isinstance(X.state_space, Range) assert X.index_set == S.Naturals0 assert isinstance(X.transition_probabilities, MatrixSymbol) t = symbols('t', positive=True, integer=True) assert isinstance(X[t], RandomIndexedSymbol) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain(1)) raises(NotImplementedError, lambda: X(t)) nz = Symbol('n', integer=True) TZ = MatrixSymbol('M', nz, nz) SZ = Range(nz) YZ = DiscreteMarkovChain('Y', SZ, TZ) assert P(Eq(YZ[2], 1), Eq(YZ[1], 0)) == TZ[0, 1] raises(ValueError, lambda: sample_stochastic_process(t)) raises(ValueError, lambda: next(sample_stochastic_process(X))) # pass name and state_space # any hashable object should be a valid state # states should be valid as a tuple/set/list/Tuple/Range sym, rainy, cloudy, sunny = symbols('a Rainy Cloudy Sunny', real=True) state_spaces = [(1, 2, 3), [Str('Hello'), sym, DiscreteMarkovChain], Tuple(1, exp(sym), Str('World'), sympify=False), Range(-1, 5, 2), [rainy, cloudy, sunny]] chains = [DiscreteMarkovChain("Y", state_space) for state_space in state_spaces] for i, Y in enumerate(chains): assert isinstance(Y.transition_probabilities, MatrixSymbol) assert Y.state_space == state_spaces[i] or Y.state_space == FiniteSet(*state_spaces[i]) assert Y.number_of_states == 3 with ignore_warnings(UserWarning): # TODO: Restore tests once warnings are removed assert P(Eq(Y[2], 1), Eq(Y[0], 2), evaluate=False) == Probability(Eq(Y[2], 1), Eq(Y[0], 2)) assert E(Y[0]) == Expectation(Y[0]) raises(ValueError, lambda: next(sample_stochastic_process(Y))) raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1)))) Y = DiscreteMarkovChain("Y", Range(1, t, 2)) assert Y.number_of_states == ceiling((t-1)/2) # pass name and transition_probabilities chains = [DiscreteMarkovChain("Y", trans_probs=Matrix([[]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[0, 1], [1, 0]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[pi, 1-pi], [sym, 1-sym]]))] for Z in chains: assert Z.number_of_states == Z.transition_probabilities.shape[0] assert isinstance(Z.transition_probabilities, ImmutableDenseMatrix) # pass name, state_space and transition_probabilities T = Matrix([[0.5, 0.2, 0.3],[0.2, 0.5, 0.3],[0.2, 0.3, 0.5]]) TS = MatrixSymbol('T', 3, 3) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) YS = DiscreteMarkovChain("Y", ['One', 'Two', 3], TS) assert YS._transient2transient() == None assert YS._transient2absorbing() == None assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3]) raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol)) assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2) assert (P(Eq(YS[3], 2), Eq(YS[1], 1)) - (TS[0, 2]*TS[1, 0] + TS[1, 1]*TS[1, 2] + TS[1, 2]*TS[2, 2])).simplify() == 0 assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1)) assert P(Eq(YS[3], 3), Eq(YS[1], 1)) == TS[0, 2]*TS[1, 0] + TS[1, 1]*TS[1, 2] + TS[1, 2]*TS[2, 2] TO = Matrix([[0.25, 0.75, 0],[0, 0.25, 0.75],[0.75, 0, 0.25]]) assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float(0.375, 3) with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed assert E(Y[3], evaluate=False) == Expectation(Y[3]) assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3) TSO = MatrixSymbol('T', 4, 4) raises(ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO)))) raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M'))) raises(ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4))) raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6))) raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1))) # extended tests for probability queries TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]]) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Probability(Eq(Y[0], 0)), Rational(1, 4)) & TransitionMatrixOf(Y, TO1)) == Rational(1, 16) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \ Probability(Eq(Y[0], 0))/4 assert P(Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P(Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P(Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)) == 0.1*Probability(Eq(Y[0], 0)) # testing properties of Markov chain TO2 = Matrix([[S.One, 0, 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]]) TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]]) Y2 = DiscreteMarkovChain('Y', trans_probs=TO2) Y3 = DiscreteMarkovChain('Y', trans_probs=TO3) assert Y3._transient2absorbing() == None raises (ValueError, lambda: Y3.fundamental_matrix()) assert Y2.is_absorbing_chain() == True assert Y3.is_absorbing_chain() == False TO4 = Matrix([[Rational(1, 5), Rational(2, 5), Rational(2, 5)], [Rational(1, 10), S.Half, Rational(2, 5)], [Rational(3, 5), Rational(3, 10), Rational(1, 10)]]) Y4 = DiscreteMarkovChain('Y', trans_probs=TO4) w = ImmutableMatrix([[Rational(11, 39), Rational(16, 39), Rational(4, 13)]]) assert Y4.limiting_distribution == w assert Y4.is_regular() == True TS1 = MatrixSymbol('T', 3, 3) Y5 = DiscreteMarkovChain('Y', trans_probs=TS1) assert Y5.limiting_distribution(w, TO4).doit() == True assert Y5.stationary_distribution(condition_set=True).subs(TS1, TO4).contains(w).doit() == S.true TO6 = Matrix([[S.One, 0, 0, 0, 0],[S.Half, 0, S.Half, 0, 0],[0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half], [0, 0, 0, 0, 1]]) Y6 = DiscreteMarkovChain('Y', trans_probs=TO6) assert Y6._transient2absorbing() == ImmutableMatrix([[S.Half, 0], [0, 0], [0, S.Half]]) assert Y6._transient2transient() == ImmutableMatrix([[0, S.Half, 0], [S.Half, 0, S.Half], [0, S.Half, 0]]) assert Y6.fundamental_matrix() == ImmutableMatrix([[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One], [S.Half, S.One, Rational(3, 2)]]) assert Y6.absorbing_probabilities() == ImmutableMatrix([[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half], [Rational(1, 4), Rational(3, 4)]]) # test for zero-sized matrix functionality X = DiscreteMarkovChain('X', trans_probs=Matrix([[]])) assert X.number_of_states == 0 assert X.stationary_distribution() == Matrix([[]]) # test communication_class # see https://drive.google.com/drive/folders/1HbxLlwwn2b3U8Lj7eb_ASIUb5vYaNIjg?usp=sharing # tutorial 2.pdf TO7 = Matrix([[0, 5, 5, 0, 0], [0, 0, 0, 10, 0], [5, 0, 5, 0, 0], [0, 10, 0, 0, 0], [0, 3, 0, 3, 4]])/10 Y7 = DiscreteMarkovChain('Y', trans_probs=TO7) tuples = Y7.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([1, 3], [0, 2], [4]) assert recurrence == (True, False, False) assert periods == (2, 1, 1) TO8 = Matrix([[0, 0, 0, 10, 0, 0], [5, 0, 5, 0, 0, 0], [0, 4, 0, 0, 0, 6], [10, 0, 0, 0, 0, 0], [0, 10, 0, 0, 0, 0], [0, 0, 0, 5, 5, 0]])/10 Y8 = DiscreteMarkovChain('Y', trans_probs=TO8) tuples = Y8.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([0, 3], [1, 2, 5, 4]) assert recurrence == (True, False) assert periods == (2, 2) TO9 = Matrix([[2, 0, 0, 3, 0, 0, 3, 2, 0, 0], [0, 10, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 2, 0, 0, 0, 0, 0, 3, 3], [0, 0, 0, 3, 0, 0, 6, 1, 0, 0], [0, 0, 0, 0, 5, 5, 0, 0, 0, 0], [0, 0, 0, 0, 0, 10, 0, 0, 0, 0], [4, 0, 0, 5, 0, 0, 1, 0, 0, 0], [2, 0, 0, 4, 0, 0, 2, 2, 0, 0], [3, 0, 1, 0, 0, 0, 0, 0, 4, 2], [0, 0, 4, 0, 0, 0, 0, 0, 3, 3]])/10 Y9 = DiscreteMarkovChain('Y', trans_probs=TO9) tuples = Y9.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([0, 3, 6, 7], [1], [2, 8, 9], [5], [4]) assert recurrence == (True, True, False, True, False) assert periods == (1, 1, 1, 1, 1) # test custom state space Y10 = DiscreteMarkovChain('Y', [1, 2, 3], TO2) tuples = Y10.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([1], [2, 3]) assert recurrence == (True, False) assert periods == (1, 1) # testing miscellaneous queries T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)], [Rational(1, 3), 0, Rational(2, 3)], [S.Half, S.Half, 0]]) X = DiscreteMarkovChain('X', [0, 1, 2], T) assert P(Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3) assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9) raises(ValueError, lambda: E(X[1], Eq(X[2], 1))) raises(ValueError, lambda: DiscreteMarkovChain('X', [0, 1], T)) # testing miscellaneous queries with different state space X = DiscreteMarkovChain('X', ['A', 'B', 'C'], T) assert P(Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) a = X.state_space.args[0] c = X.state_space.args[2] assert (E(X[1] ** 2, Eq(X[0], 1)) - (a**2/3 + 2*c**2/3)).simplify() == 0 assert (variance(X[1], Eq(X[0], 1)) - (2*(-a/3 + c/3)**2/3 + (2*a/3 - 2*c/3)**2/3)).simplify() == 0 raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
from sympy import * from sympy.stats import Normal, density, E, variance var("tau nact pact dt std damping scale tau_threshold act_threshold", real=True) var("dt std alpha scale time_constant", real=True, positive=True) noise = Normal("noise", 0, std) alpha = 1 - exp(-dt/time_constant) #nact = alpha*pact + (1 - alpha)*(atan((tau - tau_threshold)*scale) + noise) #dact = (nact - pact).simplify() #pprint(dact) #nact = pact + (-damping*pact + atan((tau - tau_threshold)*scale) + noise)*dt dact = -alpha*pact + atan((tau - tau_threshold)*scale)*dt + noise*sqrt(dt) print(dact) pprint(density(dact)) m = E(dact) v = variance(dact).simplify() print(m) print(v)
def test_DiscreteMarkovChain(): # pass only the name X = DiscreteMarkovChain("X") assert X.state_space == S.Reals assert X.index_set == S.Naturals0 assert X.transition_probabilities == None t = symbols('t', positive=True, integer=True) assert isinstance(X[t], RandomIndexedSymbol) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain(1)) raises(NotImplementedError, lambda: X(t)) # pass name and state_space Y = DiscreteMarkovChain("Y", [1, 2, 3]) assert Y.transition_probabilities == None assert Y.state_space == FiniteSet(1, 2, 3) assert P(Eq(Y[2], 1), Eq(Y[0], 2)) == Probability(Eq(Y[2], 1), Eq(Y[0], 2)) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1)))) # pass name, state_space and transition_probabilities T = Matrix([[0.5, 0.2, 0.3], [0.2, 0.5, 0.3], [0.2, 0.3, 0.5]]) TS = MatrixSymbol('T', 3, 3) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) YS = DiscreteMarkovChain("Y", [0, 1, 2], TS) assert YS._transient2transient() == None assert YS._transient2absorbing() == None assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3]) raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol)) assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2) assert str(P(Eq(YS[3], 2), Eq(YS[1], 1))) == \ "T[0, 2]*T[1, 0] + T[1, 1]*T[1, 2] + T[1, 2]*T[2, 2]" TO = Matrix([[0.25, 0.75, 0], [0, 0.25, 0.75], [0.75, 0, 0.25]]) assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float( 0.375, 3) assert E(Y[3], evaluate=False) == Expectation(Y[3]) assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3) TSO = MatrixSymbol('T', 4, 4) raises( ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO)))) raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M'))) raises( ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4))) raises(IndexError, lambda: str(P(Eq(YS[3], 3), Eq(YS[1], 1)))) raises(ValueError, lambda: str(P(Eq(YS[1], 1), Eq(YS[2], 2)))) raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6))) raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1))) # extended tests for probability queries TO1 = Matrix([[S(1) / 4, S(3) / 4, 0], [S(1) / 3, S(1) / 3, S(1) / 3], [0, S(1) / 4, S(3) / 4]]) assert P( And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Probability(Eq(Y[0], 0)), S(1) / 4) & TransitionMatrixOf(Y, TO1)) == S(1) / 16 assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \ Probability(Eq(Y[0], 0))/4 assert P( Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == S(1) / 4 assert P( Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == S(0) raises( ValueError, lambda: str( P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)))) # testing properties of Markov chain TO2 = Matrix([[S(1), 0, 0], [S(1) / 3, S(1) / 3, S(1) / 3], [0, S(1) / 4, S(3) / 4]]) TO3 = Matrix([[S(1) / 4, S(3) / 4, 0], [S(1) / 3, S(1) / 3, S(1) / 3], [0, S(1) / 4, S(3) / 4]]) Y2 = DiscreteMarkovChain('Y', trans_probs=TO2) Y3 = DiscreteMarkovChain('Y', trans_probs=TO3) assert Y3._transient2absorbing() == None raises(ValueError, lambda: Y3.fundamental_matrix()) assert Y2.is_absorbing_chain() == True assert Y3.is_absorbing_chain() == False TO4 = Matrix([[S(1) / 5, S(2) / 5, S(2) / 5], [S(1) / 10, S(1) / 2, S(2) / 5], [S(3) / 5, S(3) / 10, S(1) / 10]]) Y4 = DiscreteMarkovChain('Y', trans_probs=TO4) w = ImmutableMatrix([[S(11) / 39, S(16) / 39, S(4) / 13]]) assert Y4.limiting_distribution == w assert Y4.is_regular() == True TS1 = MatrixSymbol('T', 3, 3) Y5 = DiscreteMarkovChain('Y', trans_probs=TS1) assert Y5.limiting_distribution(w, TO4).doit() == True TO6 = Matrix([[S(1), 0, 0, 0, 0], [S(1) / 2, 0, S(1) / 2, 0, 0], [0, S(1) / 2, 0, S(1) / 2, 0], [0, 0, S(1) / 2, 0, S(1) / 2], [0, 0, 0, 0, 1]]) Y6 = DiscreteMarkovChain('Y', trans_probs=TO6) assert Y6._transient2absorbing() == ImmutableMatrix([[S(1) / 2, 0], [0, 0], [0, S(1) / 2]]) assert Y6._transient2transient() == ImmutableMatrix( [[0, S(1) / 2, 0], [S(1) / 2, 0, S(1) / 2], [0, S(1) / 2, 0]]) assert Y6.fundamental_matrix() == ImmutableMatrix( [[S(3) / 2, S(1), S(1) / 2], [S(1), S(2), S(1)], [S(1) / 2, S(1), S(3) / 2]]) assert Y6.absorbing_probabilites() == ImmutableMatrix( [[S(3) / 4, S(1) / 4], [S(1) / 2, S(1) / 2], [S(1) / 4, S(3) / 4]]) # testing miscellaneous queries T = Matrix([[S(1) / 2, S(1) / 4, S(1) / 4], [S(1) / 3, 0, S(2) / 3], [S(1) / 2, S(1) / 2, 0]]) X = DiscreteMarkovChain('X', [0, 1, 2], T) assert P( Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), S(1) / 4) & Eq(P(Eq(X[1], 1)), S(1) / 4)) == S(1) / 12 assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == S(2) / 3 assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) == S(0) assert P(Ne(X[2], 2), Eq(X[1], 1)) == S(1) / 3 assert E(X[1]**2, Eq(X[0], 1)) == S(8) / 3 assert variance(X[1], Eq(X[0], 1)) == S(8) / 9 raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
def test_dice(): # TODO: Make iid method! X, Y, Z = Die('X', 6), Die('Y', 6), Die('Z', 6) a, b, t, p = symbols('a b t p') assert E(X) == 3 + S.Half assert variance(X) == Rational(35, 12) assert E(X + Y) == 7 assert E(X + X) == 7 assert E(a * X + b) == a * E(X) + b assert variance(X + Y) == variance(X) + variance(Y) == cmoment(X + Y, 2) assert variance(X + X) == 4 * variance(X) == cmoment(X + X, 2) assert cmoment(X, 0) == 1 assert cmoment(4 * X, 3) == 64 * cmoment(X, 3) assert covariance(X, Y) is S.Zero assert covariance(X, X + Y) == variance(X) assert density(Eq(cos(X * S.Pi), 1))[True] == S.Half assert correlation(X, Y) == 0 assert correlation(X, Y) == correlation(Y, X) assert smoment(X + Y, 3) == skewness(X + Y) assert smoment(X + Y, 4) == kurtosis(X + Y) assert smoment(X, 0) == 1 assert P(X > 3) == S.Half assert P(2 * X > 6) == S.Half assert P(X > Y) == Rational(5, 12) assert P(Eq(X, Y)) == P(Eq(X, 1)) assert E(X, X > 3) == 5 == moment(X, 1, 0, X > 3) assert E(X, Y > 3) == E(X) == moment(X, 1, 0, Y > 3) assert E(X + Y, Eq(X, Y)) == E(2 * X) assert moment(X, 0) == 1 assert moment(5 * X, 2) == 25 * moment(X, 2) assert quantile(X)(p) == Piecewise((nan, (p > 1) | (p < 0)),\ (S.One, p <= Rational(1, 6)), (S(2), p <= Rational(1, 3)), (S(3), p <= S.Half),\ (S(4), p <= Rational(2, 3)), (S(5), p <= Rational(5, 6)), (S(6), p <= 1)) assert P(X > 3, X > 3) is S.One assert P(X > Y, Eq(Y, 6)) is S.Zero assert P(Eq(X + Y, 12)) == Rational(1, 36) assert P(Eq(X + Y, 12), Eq(X, 6)) == Rational(1, 6) assert density(X + Y) == density(Y + Z) != density(X + X) d = density(2 * X + Y**Z) assert d[S(22)] == Rational(1, 108) and d[S(4100)] == Rational( 1, 216) and S(3130) not in d assert pspace(X).domain.as_boolean() == Or( *[Eq(X.symbol, i) for i in [1, 2, 3, 4, 5, 6]]) assert where(X > 3).set == FiniteSet(4, 5, 6) assert characteristic_function(X)(t) == exp(6 * I * t) / 6 + exp( 5 * I * t) / 6 + exp(4 * I * t) / 6 + exp(3 * I * t) / 6 + exp( 2 * I * t) / 6 + exp(I * t) / 6 assert moment_generating_function(X)( t) == exp(6 * t) / 6 + exp(5 * t) / 6 + exp(4 * t) / 6 + exp( 3 * t) / 6 + exp(2 * t) / 6 + exp(t) / 6 assert median(X) == FiniteSet(3, 4) D = Die('D', 7) assert median(D) == FiniteSet(4) # Bayes test for die BayesTest(X > 3, X + Y < 5) BayesTest(Eq(X - Y, Z), Z > Y) BayesTest(X > 3, X > 2) # arg test for die raises(ValueError, lambda: Die('X', -1)) # issue 8105: negative sides. raises(ValueError, lambda: Die('X', 0)) raises(ValueError, lambda: Die('X', 1.5)) # issue 8103: non integer sides. # symbolic test for die n, k = symbols('n, k', positive=True) D = Die('D', n) dens = density(D).dict assert dens == Density(DieDistribution(n)) assert set(dens.subs(n, 4).doit().keys()) == set([1, 2, 3, 4]) assert set(dens.subs(n, 4).doit().values()) == set([Rational(1, 4)]) k = Dummy('k', integer=True) assert E(D).dummy_eq(Sum(Piecewise((k / n, k <= n), (0, True)), (k, 1, n))) assert variance(D).subs(n, 6).doit() == Rational(35, 12) ki = Dummy('ki') cumuf = cdf(D)(k) assert cumuf.dummy_eq( Sum(Piecewise((1 / n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, k))) assert cumuf.subs({n: 6, k: 2}).doit() == Rational(1, 3) t = Dummy('t') cf = characteristic_function(D)(t) assert cf.dummy_eq( Sum(Piecewise((exp(ki * I * t) / n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, n))) assert cf.subs( n, 3).doit() == exp(3 * I * t) / 3 + exp(2 * I * t) / 3 + exp(I * t) / 3 mgf = moment_generating_function(D)(t) assert mgf.dummy_eq( Sum(Piecewise((exp(ki * t) / n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, n))) assert mgf.subs(n, 3).doit() == exp(3 * t) / 3 + exp(2 * t) / 3 + exp(t) / 3
def test_zeta(): s = S(5) x = Zeta('x', s) assert E(x) == zeta(s - 1) / zeta(s) assert simplify( variance(x)) == (zeta(s) * zeta(s - 2) - zeta(s - 1)**2) / zeta(s)**2
def test_literal_probability(): X = Normal('X', 2, 3) Y = Normal('Y', 3, 4) Z = Poisson('Z', 4) W = Poisson('W', 3) x = symbols('x', real=True) y, w, z = symbols('y, w, z') assert Probability(X > 0).evaluate_integral() == probability(X > 0) assert Probability(X > x).evaluate_integral() == probability(X > x) assert Probability(X > 0).rewrite(Integral).doit() == probability(X > 0) assert Probability(X > x).rewrite(Integral).doit() == probability(X > x) assert Expectation(X).evaluate_integral() == expectation(X) assert Expectation(X).rewrite(Integral).doit() == expectation(X) assert Expectation(X**2).evaluate_integral() == expectation(X**2) assert Expectation(x * X).args == (x * X, ) assert Expectation(x * X).doit() == x * Expectation(X) assert Expectation(2 * X + 3 * Y + z * X * Y).doit( ) == 2 * Expectation(X) + 3 * Expectation(Y) + z * Expectation(X * Y) assert Expectation(2 * X + 3 * Y + z * X * Y).args == (2 * X + 3 * Y + z * X * Y, ) assert Expectation(sin(X)) == Expectation(sin(X)).doit() assert Expectation( 2 * x * sin(X) * Y + y * X**2 + z * X * Y).doit() == 2 * x * Expectation(sin(X) * Y) + y * Expectation( X**2) + z * Expectation(X * Y) assert Variance(w).args == (w, ) assert Variance(w).doit() == 0 assert Variance(X).evaluate_integral() == Variance(X).rewrite( Integral).doit() == variance(X) assert Variance(X + z).args == (X + z, ) assert Variance(X + z).doit() == Variance(X) assert Variance(X * Y).args == (Mul(X, Y), ) assert type(Variance(X * Y)) == Variance assert Variance(z * X).doit() == z**2 * Variance(X) assert Variance( X + Y).doit() == Variance(X) + Variance(Y) + 2 * Covariance(X, Y) assert Variance(X + Y + Z + W).doit() == (Variance(X) + Variance(Y) + Variance(Z) + Variance(W) + 2 * Covariance(X, Y) + 2 * Covariance(X, Z) + 2 * Covariance(X, W) + 2 * Covariance(Y, Z) + 2 * Covariance(Y, W) + 2 * Covariance(W, Z)) assert Variance(X**2).evaluate_integral() == variance(X**2) assert Variance(X**2) == Variance(X**2) assert Variance(x * X**2).doit() == x**2 * Variance(X**2) assert Variance(sin(X)).args == (sin(X), ) assert Variance(sin(X)).doit() == Variance(sin(X)) assert Variance(x * sin(X)).doit() == x**2 * Variance(sin(X)) assert Covariance(w, z).args == (w, z) assert Covariance(w, z).doit() == 0 assert Covariance(X, w).doit() == 0 assert Covariance(w, X).doit() == 0 assert Covariance(X, Y).args == (X, Y) assert type(Covariance(X, Y)) == Covariance assert Covariance(z * X + 3, Y).doit() == z * Covariance(X, Y) assert Covariance(X, X).args == (X, X) assert Covariance(X, X).doit() == Variance(X) assert Covariance(z * X + 3, w * Y + 4).doit() == w * z * Covariance(X, Y) assert Covariance(X, Y) == Covariance(Y, X) assert Covariance(X + Y, Z + W).doit() == Covariance(W, X) + Covariance( W, Y) + Covariance(X, Z) + Covariance(Y, Z) assert Covariance( x * X + y * Y, z * Z + w * W).doit() == (x * w * Covariance(W, X) + w * y * Covariance(W, Y) + x * z * Covariance(X, Z) + y * z * Covariance(Y, Z)) assert Covariance(x * X**2 + y * sin(Y), z * Y * Z**2 + w * W).doit() == (w * x * Covariance(W, X**2) + w * y * Covariance(sin(Y), W) + x * z * Covariance(Y * Z**2, X**2) + y * z * Covariance(Y * Z**2, sin(Y))) assert Covariance(X, X**2).doit() == Covariance(X, X**2) assert Covariance(X, sin(X)).doit() == Covariance(sin(X), X) assert Covariance(X**2, sin(X) * Y).doit() == Covariance(sin(X) * Y, X**2)
def _eval_rewrite_as_Integral(self, arg, condition=None, **kwargs): return variance(self.args[0], self._condition, evaluate=False)
def test_DiscreteMarkovChain(): # pass only the name X = DiscreteMarkovChain("X") assert isinstance(X.state_space, Range) assert isinstance(X.index_of, Range) assert not X._is_numeric assert X.index_set == S.Naturals0 assert isinstance(X.transition_probabilities, MatrixSymbol) t = symbols('t', positive=True, integer=True) assert isinstance(X[t], RandomIndexedSymbol) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain(1)) raises(NotImplementedError, lambda: X(t)) raises(ValueError, lambda: sample_stochastic_process(t)) raises(ValueError, lambda: next(sample_stochastic_process(X))) # pass name and state_space # any hashable object should be a valid state # states should be valid as a tuple/set/list/Tuple/Range sym = symbols('a', real=True) state_spaces = [(1, 2, 3), [Str('Hello'), sym, DiscreteMarkovChain], Tuple(1, exp(sym), Str('World'), sympify=False), Range(-1, 7, 2)] chains = [ DiscreteMarkovChain("Y", state_spaces[0]), DiscreteMarkovChain("Y", state_spaces[1]), DiscreteMarkovChain("Y", state_spaces[2]) ] for i, Y in enumerate(chains): assert isinstance(Y.transition_probabilities, MatrixSymbol) assert Y.state_space == Tuple(*state_spaces[i]) assert Y.number_of_states == 3 assert not Y._is_numeric # because no transition matrix is provided assert Y.index_of[state_spaces[i][0]] == 0 assert Y.index_of[state_spaces[i][1]] == 1 assert Y.index_of[state_spaces[i][2]] == 2 with ignore_warnings( UserWarning): # TODO: Restore tests once warnings are removed assert P(Eq(Y[2], 1), Eq(Y[0], 2), evaluate=False) == Probability(Eq(Y[2], 1), Eq(Y[0], 2)) assert E(Y[0]) == Expectation(Y[0]) raises(ValueError, lambda: next(sample_stochastic_process(Y))) raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1)))) Y = DiscreteMarkovChain("Y", Range(1, t, 2)) assert Y.number_of_states == ceiling((t - 1) / 2) raises(NotImplementedError, lambda: Y.index_of) # pass name and transition_probabilities chains = [ DiscreteMarkovChain("Y", trans_probs=Matrix([[]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[0, 1], [1, 0]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[pi, 1 - pi], [sym, 1 - sym]])) ] for Z in chains: assert Z.number_of_states == Z.transition_probabilities.shape[0] assert isinstance(Z.transition_probabilities, ImmutableDenseMatrix) assert isinstance(Z.state_space, Tuple) assert Z._is_numeric # pass name, state_space and transition_probabilities T = Matrix([[0.5, 0.2, 0.3], [0.2, 0.5, 0.3], [0.2, 0.3, 0.5]]) TS = MatrixSymbol('T', 3, 3) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) YS = DiscreteMarkovChain("Y", ['One', 'Two', 3], TS) assert YS._transient2transient() == None assert YS._transient2absorbing() == None assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3]) raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol)) assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2) assert (P(Eq(YS[3], 2), Eq(YS[1], 1)) - (TS[0, 2] * TS[1, 0] + TS[1, 1] * TS[1, 2] + TS[1, 2] * TS[2, 2])).simplify() == 0 assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1)) assert P(Eq(YS[3], 3), Eq(YS[1], 1)) is S.Zero TO = Matrix([[0.25, 0.75, 0], [0, 0.25, 0.75], [0.75, 0, 0.25]]) assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float( 0.375, 3) with ignore_warnings( UserWarning): ### TODO: Restore tests once warnings are removed assert E(Y[3], evaluate=False) == Expectation(Y[3]) assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3) TSO = MatrixSymbol('T', 4, 4) raises( ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO)))) raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M'))) raises( ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4))) raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6))) raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1))) # extended tests for probability queries TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) assert P( And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Probability(Eq(Y[0], 0)), Rational(1, 4)) & TransitionMatrixOf(Y, TO1)) == Rational(1, 16) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \ Probability(Eq(Y[0], 0))/4 assert P( Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P( Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P( Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P( Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)) == 0.1 * Probability(Eq(Y[0], 0)) # testing properties of Markov chain TO2 = Matrix([[S.One, 0, 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) Y2 = DiscreteMarkovChain('Y', trans_probs=TO2) Y3 = DiscreteMarkovChain('Y', trans_probs=TO3) assert Y3._transient2absorbing() == None raises(ValueError, lambda: Y3.fundamental_matrix()) assert Y2.is_absorbing_chain() == True assert Y3.is_absorbing_chain() == False TO4 = Matrix([[Rational(1, 5), Rational(2, 5), Rational(2, 5)], [Rational(1, 10), S.Half, Rational(2, 5)], [Rational(3, 5), Rational(3, 10), Rational(1, 10)]]) Y4 = DiscreteMarkovChain('Y', trans_probs=TO4) w = ImmutableMatrix([[Rational(11, 39), Rational(16, 39), Rational(4, 13)]]) assert Y4.limiting_distribution == w assert Y4.is_regular() == True TS1 = MatrixSymbol('T', 3, 3) Y5 = DiscreteMarkovChain('Y', trans_probs=TS1) assert Y5.limiting_distribution(w, TO4).doit() == True TO6 = Matrix([[S.One, 0, 0, 0, 0], [S.Half, 0, S.Half, 0, 0], [0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half], [0, 0, 0, 0, 1]]) Y6 = DiscreteMarkovChain('Y', trans_probs=TO6) assert Y6._transient2absorbing() == ImmutableMatrix([[S.Half, 0], [0, 0], [0, S.Half]]) assert Y6._transient2transient() == ImmutableMatrix([[0, S.Half, 0], [S.Half, 0, S.Half], [0, S.Half, 0]]) assert Y6.fundamental_matrix() == ImmutableMatrix( [[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One], [S.Half, S.One, Rational(3, 2)]]) assert Y6.absorbing_probabilities() == ImmutableMatrix( [[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half], [Rational(1, 4), Rational(3, 4)]]) # testing miscellaneous queries T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)], [Rational(1, 3), 0, Rational(2, 3)], [S.Half, S.Half, 0]]) X = DiscreteMarkovChain('X', [0, 1, 2], T) assert P( Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3) assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9) raises(ValueError, lambda: E(X[1], Eq(X[2], 1))) raises(ValueError, lambda: DiscreteMarkovChain('X', [0, 1], T)) # testing miscellaneous queries with different state space X = DiscreteMarkovChain('X', ['A', 'B', 'C'], T) assert P( Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) a = X.state_space.args[0] c = X.state_space.args[2] assert (E(X[1]**2, Eq(X[0], 1)) - (a**2 / 3 + 2 * c**2 / 3)).simplify() == 0 assert (variance(X[1], Eq(X[0], 1)) - (2 * (-a / 3 + c / 3)**2 / 3 + (2 * a / 3 - 2 * c / 3)**2 / 3)).simplify() == 0 raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
def test_ContinuousMarkovChain(): T1 = Matrix([[S(-2), S(2), S.Zero], [S.Zero, S.NegativeOne, S.One], [Rational(3, 2), Rational(3, 2), S(-3)]]) C1 = ContinuousMarkovChain('C', [0, 1, 2], T1) assert C1.limiting_distribution() == ImmutableMatrix( [[Rational(3, 19), Rational(12, 19), Rational(4, 19)]]) T2 = Matrix([[-S.One, S.One, S.Zero], [S.One, -S.One, S.Zero], [S.Zero, S.One, -S.One]]) C2 = ContinuousMarkovChain('C', [0, 1, 2], T2) A, t = C2.generator_matrix, symbols('t', positive=True) assert C2.transition_probabilities(A)(t) == Matrix( [[S.Half + exp(-2 * t) / 2, S.Half - exp(-2 * t) / 2, 0], [S.Half - exp(-2 * t) / 2, S.Half + exp(-2 * t) / 2, 0], [ S.Half - exp(-t) + exp(-2 * t) / 2, S.Half - exp(-2 * t) / 2, exp(-t) ]]) with ignore_warnings( UserWarning): ### TODO: Restore tests once warnings are removed assert P(Eq(C2(1), 1), Eq(C2(0), 1), evaluate=False) == Probability(Eq(C2(1), 1), Eq(C2(0), 1)) assert P(Eq(C2(1), 1), Eq(C2(0), 1)) == exp(-2) / 2 + S.Half assert P( Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 1), Eq(P(Eq(C2(1), 0)), S.Half)) == (Rational(1, 4) - exp(-2) / 4) * (exp(-2) / 2 + S.Half) assert P( Not(Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 2)) | (Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 2)), Eq(P(Eq(C2(1), 0)), Rational(1, 4)) & Eq(P(Eq(C2(1), 1)), Rational(1, 4))) is S.One assert E(C2(Rational(3, 2)), Eq(C2(0), 2)) == -exp(-3) / 2 + 2 * exp(Rational(-3, 2)) + S.Half assert variance(C2(Rational(3, 2)), Eq( C2(0), 1)) == ((S.Half - exp(-3) / 2)**2 * (exp(-3) / 2 + S.Half) + (Rational(-1, 2) - exp(-3) / 2)**2 * (S.Half - exp(-3) / 2)) raises(KeyError, lambda: P(Eq(C2(1), 0), Eq(P(Eq(C2(1), 1)), S.Half))) assert P(Eq(C2(1), 0), Eq(P(Eq(C2(5), 1)), S.Half)) == Probability(Eq(C2(1), 0)) TS1 = MatrixSymbol('G', 3, 3) CS1 = ContinuousMarkovChain('C', [0, 1, 2], TS1) A = CS1.generator_matrix assert CS1.transition_probabilities(A)(t) == exp(t * A) C3 = ContinuousMarkovChain( 'C', [Symbol('0'), Symbol('1'), Symbol('2')], T2) assert P(Eq(C3(1), 1), Eq(C3(0), 1)) == exp(-2) / 2 + S.Half assert P(Eq(C3(1), Symbol('1')), Eq(C3(0), Symbol('1'))) == exp(-2) / 2 + S.Half #test probability queries G = Matrix([[-S(1), Rational(1, 10), Rational(9, 10)], [Rational(2, 5), -S(1), Rational(3, 5)], [Rational(1, 2), Rational(1, 2), -S(1)]]) C = ContinuousMarkovChain('C', state_space=[0, 1, 2], gen_mat=G) assert P(Eq(C(7.385), C(3.19)), Eq(C(0.862), 0)).round(5) == Float(0.35469, 5) assert P(Gt(C(98.715), C(19.807)), Eq(C(11.314), 2)).round(5) == Float(0.32452, 5) assert P(Le(C(5.9), C(10.112)), Eq(C(4), 1)).round(6) == Float(0.675214, 6) assert Float(P(Eq(C(7.32), C(2.91)), Eq(C(2.63), 1)), 14) == Float(1 - P(Ne(C(7.32), C(2.91)), Eq(C(2.63), 1)), 14) assert Float(P(Gt(C(3.36), C(1.101)), Eq(C(0.8), 2)), 14) == Float(1 - P(Le(C(3.36), C(1.101)), Eq(C(0.8), 2)), 14) assert Float(P(Lt(C(4.9), C(2.79)), Eq(C(1.61), 0)), 14) == Float(1 - P(Ge(C(4.9), C(2.79)), Eq(C(1.61), 0)), 14) assert P(Eq(C(5.243), C(10.912)), Eq(C(2.174), 1)) == P(Eq(C(10.912), C(5.243)), Eq(C(2.174), 1)) assert P(Gt(C(2.344), C(9.9)), Eq(C(1.102), 1)) == P(Lt(C(9.9), C(2.344)), Eq(C(1.102), 1)) assert P(Ge(C(7.87), C(1.008)), Eq(C(0.153), 1)) == P(Le(C(1.008), C(7.87)), Eq(C(0.153), 1)) #test symbolic queries a, b, c, d = symbols('a b c d') query = P(Eq(C(a), b), Eq(C(c), d)) assert query.subs({ a: 3.65, b: 2, c: 1.78, d: 1 }).evalf().round(10) == P(Eq(C(3.65), 2), Eq(C(1.78), 1)).round(10) query_gt = P(Gt(C(a), b), Eq(C(c), d)) query_le = P(Le(C(a), b), Eq(C(c), d)) assert query_gt.subs({ a: 13.2, b: 0, c: 3.29, d: 2 }).evalf() + query_le.subs({ a: 13.2, b: 0, c: 3.29, d: 2 }).evalf() == 1 query_ge = P(Ge(C(a), b), Eq(C(c), d)) query_lt = P(Lt(C(a), b), Eq(C(c), d)) assert query_ge.subs({ a: 7.43, b: 1, c: 1.45, d: 0 }).evalf() + query_lt.subs({ a: 7.43, b: 1, c: 1.45, d: 0 }).evalf() == 1 #test issue 20078 assert (2 * C(1) + 3 * C(1)).simplify() == 5 * C(1) assert (2 * C(1) - 3 * C(1)).simplify() == -C(1) assert (2 * (0.25 * C(1))).simplify() == 0.5 * C(1) assert (2 * C(1) * 0.25 * C(1)).simplify() == 0.5 * C(1)**2 assert (C(1)**2 + C(1)**3).simplify() == (C(1) + 1) * C(1)**2
def test_DiscreteMarkovChain(): # pass only the name X = DiscreteMarkovChain("X") assert isinstance(X.state_space, Range) assert X.index_set == S.Naturals0 assert isinstance(X.transition_probabilities, MatrixSymbol) t = symbols('t', positive=True, integer=True) assert isinstance(X[t], RandomIndexedSymbol) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain(1)) raises(NotImplementedError, lambda: X(t)) raises(NotImplementedError, lambda: X.communication_classes()) raises(NotImplementedError, lambda: X.canonical_form()) raises(NotImplementedError, lambda: X.decompose()) nz = Symbol('n', integer=True) TZ = MatrixSymbol('M', nz, nz) SZ = Range(nz) YZ = DiscreteMarkovChain('Y', SZ, TZ) assert P(Eq(YZ[2], 1), Eq(YZ[1], 0)) == TZ[0, 1] raises(ValueError, lambda: sample_stochastic_process(t)) raises(ValueError, lambda: next(sample_stochastic_process(X))) # pass name and state_space # any hashable object should be a valid state # states should be valid as a tuple/set/list/Tuple/Range sym, rainy, cloudy, sunny = symbols('a Rainy Cloudy Sunny', real=True) state_spaces = [(1, 2, 3), [Str('Hello'), sym, DiscreteMarkovChain], Tuple(1, exp(sym), Str('World'), sympify=False), Range(-1, 5, 2), [rainy, cloudy, sunny]] chains = [ DiscreteMarkovChain("Y", state_space) for state_space in state_spaces ] for i, Y in enumerate(chains): assert isinstance(Y.transition_probabilities, MatrixSymbol) assert Y.state_space == state_spaces[i] or Y.state_space == FiniteSet( *state_spaces[i]) assert Y.number_of_states == 3 with ignore_warnings( UserWarning): # TODO: Restore tests once warnings are removed assert P(Eq(Y[2], 1), Eq(Y[0], 2), evaluate=False) == Probability(Eq(Y[2], 1), Eq(Y[0], 2)) assert E(Y[0]) == Expectation(Y[0]) raises(ValueError, lambda: next(sample_stochastic_process(Y))) raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1)))) Y = DiscreteMarkovChain("Y", Range(1, t, 2)) assert Y.number_of_states == ceiling((t - 1) / 2) # pass name and transition_probabilities chains = [ DiscreteMarkovChain("Y", trans_probs=Matrix([[]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[0, 1], [1, 0]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[pi, 1 - pi], [sym, 1 - sym]])) ] for Z in chains: assert Z.number_of_states == Z.transition_probabilities.shape[0] assert isinstance(Z.transition_probabilities, ImmutableDenseMatrix) # pass name, state_space and transition_probabilities T = Matrix([[0.5, 0.2, 0.3], [0.2, 0.5, 0.3], [0.2, 0.3, 0.5]]) TS = MatrixSymbol('T', 3, 3) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) YS = DiscreteMarkovChain("Y", ['One', 'Two', 3], TS) assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3]) raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol)) assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2) assert (P(Eq(YS[3], 2), Eq(YS[1], 1)) - (TS[0, 2] * TS[1, 0] + TS[1, 1] * TS[1, 2] + TS[1, 2] * TS[2, 2])).simplify() == 0 assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1)) assert P(Eq(YS[3], 3), Eq( YS[1], 1)) == TS[0, 2] * TS[1, 0] + TS[1, 1] * TS[1, 2] + TS[1, 2] * TS[2, 2] TO = Matrix([[0.25, 0.75, 0], [0, 0.25, 0.75], [0.75, 0, 0.25]]) assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float( 0.375, 3) with ignore_warnings( UserWarning): ### TODO: Restore tests once warnings are removed assert E(Y[3], evaluate=False) == Expectation(Y[3]) assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3) TSO = MatrixSymbol('T', 4, 4) raises( ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO)))) raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M'))) raises( ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4))) raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6))) raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1))) # extended tests for probability queries TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) assert P( And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Probability(Eq(Y[0], 0)), Rational(1, 4)) & TransitionMatrixOf(Y, TO1)) == Rational(1, 16) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \ Probability(Eq(Y[0], 0))/4 assert P( Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P( Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P( Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P( Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)) == 0.1 * Probability(Eq(Y[0], 0)) # testing properties of Markov chain TO2 = Matrix([[S.One, 0, 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) Y2 = DiscreteMarkovChain('Y', trans_probs=TO2) Y3 = DiscreteMarkovChain('Y', trans_probs=TO3) assert Y3.fundamental_matrix() == ImmutableMatrix( [[176, 81, -132], [36, 141, -52], [-44, -39, 208]]) / 125 assert Y2.is_absorbing_chain() == True assert Y3.is_absorbing_chain() == False assert Y2.canonical_form() == ([0, 1, 2], TO2) assert Y3.canonical_form() == ([0, 1, 2], TO3) assert Y2.decompose() == ([0, 1, 2], TO2[0:1, 0:1], TO2[1:3, 0:1], TO2[1:3, 1:3]) assert Y3.decompose() == ([0, 1, 2], TO3, Matrix(0, 3, []), Matrix(0, 0, [])) TO4 = Matrix([[Rational(1, 5), Rational(2, 5), Rational(2, 5)], [Rational(1, 10), S.Half, Rational(2, 5)], [Rational(3, 5), Rational(3, 10), Rational(1, 10)]]) Y4 = DiscreteMarkovChain('Y', trans_probs=TO4) w = ImmutableMatrix([[Rational(11, 39), Rational(16, 39), Rational(4, 13)]]) assert Y4.limiting_distribution == w assert Y4.is_regular() == True assert Y4.is_ergodic() == True TS1 = MatrixSymbol('T', 3, 3) Y5 = DiscreteMarkovChain('Y', trans_probs=TS1) assert Y5.limiting_distribution(w, TO4).doit() == True assert Y5.stationary_distribution(condition_set=True).subs( TS1, TO4).contains(w).doit() == S.true TO6 = Matrix([[S.One, 0, 0, 0, 0], [S.Half, 0, S.Half, 0, 0], [0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half], [0, 0, 0, 0, 1]]) Y6 = DiscreteMarkovChain('Y', trans_probs=TO6) assert Y6.fundamental_matrix() == ImmutableMatrix( [[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One], [S.Half, S.One, Rational(3, 2)]]) assert Y6.absorbing_probabilities() == ImmutableMatrix( [[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half], [Rational(1, 4), Rational(3, 4)]]) TO7 = Matrix([[Rational(1, 2), Rational(1, 4), Rational(1, 4)], [Rational(1, 2), 0, Rational(1, 2)], [Rational(1, 4), Rational(1, 4), Rational(1, 2)]]) Y7 = DiscreteMarkovChain('Y', trans_probs=TO7) assert Y7.is_absorbing_chain() == False assert Y7.fundamental_matrix() == ImmutableDenseMatrix( [[Rational(86, 75), Rational(1, 25), Rational(-14, 75)], [Rational(2, 25), Rational(21, 25), Rational(2, 25)], [Rational(-14, 75), Rational(1, 25), Rational(86, 75)]]) # test for zero-sized matrix functionality X = DiscreteMarkovChain('X', trans_probs=Matrix([[]])) assert X.number_of_states == 0 assert X.stationary_distribution() == Matrix([[]]) assert X.communication_classes() == [] assert X.canonical_form() == ([], Matrix([[]])) assert X.decompose() == ([], Matrix([[]]), Matrix([[]]), Matrix([[]])) assert X.is_regular() == False assert X.is_ergodic() == False # test communication_class # see https://drive.google.com/drive/folders/1HbxLlwwn2b3U8Lj7eb_ASIUb5vYaNIjg?usp=sharing # tutorial 2.pdf TO7 = Matrix([[0, 5, 5, 0, 0], [0, 0, 0, 10, 0], [5, 0, 5, 0, 0], [0, 10, 0, 0, 0], [0, 3, 0, 3, 4]]) / 10 Y7 = DiscreteMarkovChain('Y', trans_probs=TO7) tuples = Y7.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([1, 3], [0, 2], [4]) assert recurrence == (True, False, False) assert periods == (2, 1, 1) TO8 = Matrix([[0, 0, 0, 10, 0, 0], [5, 0, 5, 0, 0, 0], [0, 4, 0, 0, 0, 6], [10, 0, 0, 0, 0, 0], [0, 10, 0, 0, 0, 0], [0, 0, 0, 5, 5, 0] ]) / 10 Y8 = DiscreteMarkovChain('Y', trans_probs=TO8) tuples = Y8.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([0, 3], [1, 2, 5, 4]) assert recurrence == (True, False) assert periods == (2, 2) TO9 = Matrix( [[2, 0, 0, 3, 0, 0, 3, 2, 0, 0], [0, 10, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 2, 0, 0, 0, 0, 0, 3, 3], [0, 0, 0, 3, 0, 0, 6, 1, 0, 0], [0, 0, 0, 0, 5, 5, 0, 0, 0, 0], [0, 0, 0, 0, 0, 10, 0, 0, 0, 0], [4, 0, 0, 5, 0, 0, 1, 0, 0, 0], [2, 0, 0, 4, 0, 0, 2, 2, 0, 0], [3, 0, 1, 0, 0, 0, 0, 0, 4, 2], [0, 0, 4, 0, 0, 0, 0, 0, 3, 3]]) / 10 Y9 = DiscreteMarkovChain('Y', trans_probs=TO9) tuples = Y9.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([0, 3, 6, 7], [1], [2, 8, 9], [5], [4]) assert recurrence == (True, True, False, True, False) assert periods == (1, 1, 1, 1, 1) # test canonical form # see https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf # example 11.13 T = Matrix([[1, 0, 0, 0, 0], [S(1) / 2, 0, S(1) / 2, 0, 0], [0, S(1) / 2, 0, S(1) / 2, 0], [0, 0, S(1) / 2, 0, S(1) / 2], [0, 0, 0, 0, S(1)]]) DW = DiscreteMarkovChain('DW', [0, 1, 2, 3, 4], T) states, A, B, C = DW.decompose() assert states == [0, 4, 1, 2, 3] assert A == Matrix([[1, 0], [0, 1]]) assert B == Matrix([[S(1) / 2, 0], [0, 0], [0, S(1) / 2]]) assert C == Matrix([[0, S(1) / 2, 0], [S(1) / 2, 0, S(1) / 2], [0, S(1) / 2, 0]]) states, new_matrix = DW.canonical_form() assert states == [0, 4, 1, 2, 3] assert new_matrix == Matrix([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [S(1) / 2, 0, 0, S(1) / 2, 0], [0, 0, S(1) / 2, 0, S(1) / 2], [0, S(1) / 2, 0, S(1) / 2, 0]]) # test regular and ergodic # https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf T = Matrix([[0, 4, 0, 0, 0], [1, 0, 3, 0, 0], [0, 2, 0, 2, 0], [0, 0, 3, 0, 1], [0, 0, 0, 4, 0]]) / 4 X = DiscreteMarkovChain('X', trans_probs=T) assert not X.is_regular() assert X.is_ergodic() T = Matrix([[0, 1], [1, 0]]) X = DiscreteMarkovChain('X', trans_probs=T) assert not X.is_regular() assert X.is_ergodic() # http://www.math.wisc.edu/~valko/courses/331/MC2.pdf T = Matrix([[2, 1, 1], [2, 0, 2], [1, 1, 2]]) / 4 X = DiscreteMarkovChain('X', trans_probs=T) assert X.is_regular() assert X.is_ergodic() # https://docs.ufpr.br/~lucambio/CE222/1S2014/Kemeny-Snell1976.pdf T = Matrix([[1, 1], [1, 1]]) / 2 X = DiscreteMarkovChain('X', trans_probs=T) assert X.is_regular() assert X.is_ergodic() # test is_absorbing_chain T = Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) X = DiscreteMarkovChain('X', trans_probs=T) assert not X.is_absorbing_chain() # https://en.wikipedia.org/wiki/Absorbing_Markov_chain T = Matrix([[1, 1, 0, 0], [0, 1, 1, 0], [1, 0, 0, 1], [0, 0, 0, 2]]) / 2 X = DiscreteMarkovChain('X', trans_probs=T) assert X.is_absorbing_chain() T = Matrix([[2, 0, 0, 0, 0], [1, 0, 1, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 0, 1], [0, 0, 0, 0, 2]]) / 2 X = DiscreteMarkovChain('X', trans_probs=T) assert X.is_absorbing_chain() # test custom state space Y10 = DiscreteMarkovChain('Y', [1, 2, 3], TO2) tuples = Y10.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([1], [2, 3]) assert recurrence == (True, False) assert periods == (1, 1) assert Y10.canonical_form() == ([1, 2, 3], TO2) assert Y10.decompose() == ([1, 2, 3], TO2[0:1, 0:1], TO2[1:3, 0:1], TO2[1:3, 1:3]) # testing miscellaneous queries T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)], [Rational(1, 3), 0, Rational(2, 3)], [S.Half, S.Half, 0]]) X = DiscreteMarkovChain('X', [0, 1, 2], T) assert P( Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3) assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9) raises(ValueError, lambda: E(X[1], Eq(X[2], 1))) raises(ValueError, lambda: DiscreteMarkovChain('X', [0, 1], T)) # testing miscellaneous queries with different state space X = DiscreteMarkovChain('X', ['A', 'B', 'C'], T) assert P( Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) a = X.state_space.args[0] c = X.state_space.args[2] assert (E(X[1]**2, Eq(X[0], 1)) - (a**2 / 3 + 2 * c**2 / 3)).simplify() == 0 assert (variance(X[1], Eq(X[0], 1)) - (2 * (-a / 3 + c / 3)**2 / 3 + (2 * a / 3 - 2 * c / 3)**2 / 3)).simplify() == 0 raises(ValueError, lambda: E(X[1], Eq(X[2], 1))) #testing queries with multiple RandomIndexedSymbols T = Matrix([[Rational(5, 10), Rational(3, 10), Rational(2, 10)], [Rational(2, 10), Rational(7, 10), Rational(1, 10)], [Rational(3, 10), Rational(3, 10), Rational(4, 10)]]) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) assert P(Eq(Y[7], Y[5]), Eq(Y[2], 0)).round(5) == Float(0.44428, 5) assert P(Gt(Y[3], Y[1]), Eq(Y[0], 0)).round(2) == Float(0.36, 2) assert P(Le(Y[5], Y[10]), Eq(Y[4], 2)).round(6) == Float(0.583120, 6) assert Float(P(Eq(Y[10], Y[5]), Eq(Y[4], 1)), 14) == Float(1 - P(Ne(Y[10], Y[5]), Eq(Y[4], 1)), 14) assert Float(P(Gt(Y[8], Y[9]), Eq(Y[3], 2)), 14) == Float(1 - P(Le(Y[8], Y[9]), Eq(Y[3], 2)), 14) assert Float(P(Lt(Y[1], Y[4]), Eq(Y[0], 0)), 14) == Float(1 - P(Ge(Y[1], Y[4]), Eq(Y[0], 0)), 14) assert P(Eq(Y[5], Y[10]), Eq(Y[2], 1)) == P(Eq(Y[10], Y[5]), Eq(Y[2], 1)) assert P(Gt(Y[1], Y[2]), Eq(Y[0], 1)) == P(Lt(Y[2], Y[1]), Eq(Y[0], 1)) assert P(Ge(Y[7], Y[6]), Eq(Y[4], 1)) == P(Le(Y[6], Y[7]), Eq(Y[4], 1)) #test symbolic queries a, b, c, d = symbols('a b c d') T = Matrix([[Rational(1, 10), Rational(4, 10), Rational(5, 10)], [Rational(3, 10), Rational(4, 10), Rational(3, 10)], [Rational(7, 10), Rational(2, 10), Rational(1, 10)]]) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) query = P(Eq(Y[a], b), Eq(Y[c], d)) assert query.subs({ a: 10, b: 2, c: 5, d: 1 }).evalf().round(4) == P(Eq(Y[10], 2), Eq(Y[5], 1)).round(4) assert query.subs({ a: 15, b: 0, c: 10, d: 1 }).evalf().round(4) == P(Eq(Y[15], 0), Eq(Y[10], 1)).round(4) query_gt = P(Gt(Y[a], b), Eq(Y[c], d)) query_le = P(Le(Y[a], b), Eq(Y[c], d)) assert query_gt.subs({ a: 5, b: 2, c: 1, d: 0 }).evalf() + query_le.subs({ a: 5, b: 2, c: 1, d: 0 }).evalf() == 1 query_ge = P(Ge(Y[a], b), Eq(Y[c], d)) query_lt = P(Lt(Y[a], b), Eq(Y[c], d)) assert query_ge.subs({ a: 4, b: 1, c: 0, d: 2 }).evalf() + query_lt.subs({ a: 4, b: 1, c: 0, d: 2 }).evalf() == 1 #test issue 20078 assert (2 * Y[1] + 3 * Y[1]).simplify() == 5 * Y[1] assert (2 * Y[1] - 3 * Y[1]).simplify() == -Y[1] assert (2 * (0.25 * Y[1])).simplify() == 0.5 * Y[1] assert ((2 * Y[1]) * (0.25 * Y[1])).simplify() == 0.5 * Y[1]**2 assert (Y[1]**2 + Y[1]**3).simplify() == (Y[1] + 1) * Y[1]**2
def test_yule_simon(): rho = S(3) x = YuleSimon('x', rho) assert simplify(E(x)) == rho / (rho - 1) assert simplify(variance(x)) == rho**2 / ((rho - 1)**2 * (rho - 2)) assert isinstance(E(x, evaluate=False), Sum)
def test_weibull(): a, b = symbols('a b', positive=True) X = Weibull('x', a, b) assert simplify(E(X)) == simplify(a * gamma(1 + 1 / b)) assert simplify(variance(X)) == simplify(a**2 * gamma(1 + 2 / b) - E(X)**2)