def as_explicit(self): """ Returns a dense Matrix with elements represented explicitly Returns an object of type ImmutableMatrix. Examples ======== >>> from sympy import Identity >>> I = Identity(3) >>> I I >>> I.as_explicit() [1, 0, 0] [0, 1, 0] [0, 0, 1] See Also ======== as_mutable: returns mutable Matrix type """ from sympy.matrices.immutable import ImmutableMatrix return ImmutableMatrix([[self[i, j] for j in range(self.cols)] for i in range(self.rows)])
def __new__(cls, *args): from sympy.matrices.immutable import ImmutableMatrix args = map(sympify, args) mat = ImmutableMatrix(*args) obj = Basic.__new__(cls, mat) return obj
def __new__(cls, *mats): from sympy.matrices.immutable import ImmutableMatrix data = [[ mats[i] if i == j else ZeroMatrix(mats[i].rows, mats[j].cols) for j in range(len(mats)) ] for i in range(len(mats))] return Basic.__new__(BlockDiagMatrix, ImmutableMatrix(data))
def blocks(self): from sympy.matrices.immutable import ImmutableMatrix mats = self.args data = [[mats[i] if i == j else ZeroMatrix(mats[i].rows, mats[j].cols) for j in range(len(mats))] for i in range(len(mats))] return ImmutableMatrix(data)
def test_as_immutable(): data = [[1, 2], [3, 4]] X = Matrix(data) assert sympify(X) == X.as_immutable() == ImmutableMatrix(data) data = {(0, 0): 1, (0, 1): 2, (1, 0): 3, (1, 1): 4} X = SparseMatrix(2, 2, data) assert sympify(X) == X.as_immutable() == ImmutableSparseMatrix(2, 2, data)
def wigner_d(J, alpha, beta, gamma): """Return the Wigner D matrix for angular momentum J. Explanation =========== J : An integer, half-integer, or SymPy symbol for the total angular momentum of the angular momentum space being rotated. alpha, beta, gamma - Real numbers representing the Euler. Angles of rotation about the so-called vertical, line of nodes, and figure axes. See [Edmonds74]_. Returns ======= A matrix representing the corresponding Euler angle rotation( in the basis of eigenvectors of `J_z`). .. math :: \\mathcal{D}_{\\alpha \\beta \\gamma} = \\exp\\big( \\frac{i\\alpha}{\\hbar} J_z\\big) \\exp\\big( \\frac{i\\beta}{\\hbar} J_y\\big) \\exp\\big( \\frac{i\\gamma}{\\hbar} J_z\\big) The components are calculated using the general form [Edmonds74]_, equation 4.1.12. Examples ======== The simplest possible example: >>> from sympy.physics.wigner import wigner_d >>> from sympy import Integer, symbols, pprint >>> half = 1/Integer(2) >>> alpha, beta, gamma = symbols("alpha, beta, gamma", real=True) >>> pprint(wigner_d(half, alpha, beta, gamma), use_unicode=True) ⎡ ⅈ⋅α ⅈ⋅γ ⅈ⋅α -ⅈ⋅γ ⎤ ⎢ ─── ─── ─── ───── ⎥ ⎢ 2 2 ⎛β⎞ 2 2 ⎛β⎞ ⎥ ⎢ ℯ ⋅ℯ ⋅cos⎜─⎟ ℯ ⋅ℯ ⋅sin⎜─⎟ ⎥ ⎢ ⎝2⎠ ⎝2⎠ ⎥ ⎢ ⎥ ⎢ -ⅈ⋅α ⅈ⋅γ -ⅈ⋅α -ⅈ⋅γ ⎥ ⎢ ───── ─── ───── ───── ⎥ ⎢ 2 2 ⎛β⎞ 2 2 ⎛β⎞⎥ ⎢-ℯ ⋅ℯ ⋅sin⎜─⎟ ℯ ⋅ℯ ⋅cos⎜─⎟⎥ ⎣ ⎝2⎠ ⎝2⎠⎦ """ d = wigner_d_small(J, beta) M = [J - i for i in range(2 * J + 1)] D = [[ exp(I * Mi * alpha) * d[i, j] * exp(I * Mj * gamma) for j, Mj in enumerate(M) ] for i, Mi in enumerate(M)] return ImmutableMatrix(D)
def doit(self, **ignored): expr = self.func(*[i.doit(**ignored) for i in self.args]) # Check for explicit matrices: from sympy import MatrixBase from sympy.matrices.immutable import ImmutableMatrix explicit = [i for i in expr.args if isinstance(i, MatrixBase)] if explicit: remainder = [i for i in expr.args if i not in explicit] expl_mat = ImmutableMatrix( [Mul.fromiter(i) for i in zip(*explicit)]).reshape(*self.shape) expr = HadamardProduct(*([expl_mat] + remainder)) return canonicalize(expr)
def test_block_index(): I = Identity(3) Z = ZeroMatrix(3, 3) B = BlockMatrix([[I, I], [I, I]]) e3 = ImmutableMatrix(eye(3)) BB = BlockMatrix([[e3, e3], [e3, e3]]) assert B[0, 0] == B[3, 0] == B[0, 3] == B[3, 3] == 1 assert B[4, 3] == B[5, 1] == 0 BB = BlockMatrix([[e3, e3], [e3, e3]]) assert B.as_explicit() == BB.as_explicit() BI = BlockMatrix([[I, Z], [Z, I]]) assert BI.as_explicit().equals(eye(6))
def test_Equality(): assert Equality(IM, IM) is S.true assert Unequality(IM, IM) is S.false assert Equality(IM, IM.subs(1, 2)) is S.false assert Unequality(IM, IM.subs(1, 2)) is S.true assert Equality(IM, 2) is S.false assert Unequality(IM, 2) is S.true M = ImmutableMatrix([x, y]) assert Equality(M, IM) is S.false assert Unequality(M, IM) is S.true assert Equality(M, M.subs(x, 2)).subs(x, 2) is S.true assert Unequality(M, M.subs(x, 2)).subs(x, 2) is S.false assert Equality(M, M.subs(x, 2)).subs(x, 3) is S.false assert Unequality(M, M.subs(x, 2)).subs(x, 3) is S.true
def test_function_return_types(): # Lets ensure that decompositions of immutable matrices remain immutable # I.e. do MatrixBase methods return the correct class? X = ImmutableMatrix([[1, 2], [3, 4]]) Y = ImmutableMatrix([[1], [0]]) q, r = X.QRdecomposition() assert (type(q), type(r)) == (ImmutableMatrix, ImmutableMatrix) assert type(X.LUsolve(Y)) == ImmutableMatrix assert type(X.QRsolve(Y)) == ImmutableMatrix X = ImmutableMatrix([[5, 2], [2, 7]]) assert X.T == X assert X.is_symmetric assert type(X.cholesky()) == ImmutableMatrix L, D = X.LDLdecomposition() assert (type(L), type(D)) == (ImmutableMatrix, ImmutableMatrix) X = ImmutableMatrix([[1, 2], [2, 1]]) assert X.is_diagonalizable() assert X.det() == -3 assert X.norm(2) == 3 assert type(X.eigenvects()[0][2][0]) == ImmutableMatrix assert type(zeros(3, 3).as_immutable().nullspace()[0]) == ImmutableMatrix X = ImmutableMatrix([[1, 0], [2, 1]]) assert type(X.lower_triangular_solve(Y)) == ImmutableMatrix assert type(X.T.upper_triangular_solve(Y)) == ImmutableMatrix assert type(X.minor_submatrix(0, 0)) == ImmutableMatrix
def test_deterimant(): assert ImmutableMatrix(4, 4, lambda i, j: i + j).det() == 0
def test_bidiagonalize(): M = Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) assert M.bidiagonalize() == M assert M.bidiagonalize(upper=False) == M assert M.bidiagonalize() == M assert M.bidiagonal_decomposition() == (M, M, M) assert M.bidiagonal_decomposition(upper=False) == (M, M, M) assert M.bidiagonalize() == M import random #Real Tests for real_test in range(2): test_values = [] row = 2 col = 2 for _ in range(row * col): value = random.randint(-1000000000, 1000000000) test_values = test_values + [value] # L -> Lower Bidiagonalization # M -> Mutable Matrix # N -> Immutable Matrix # 0 -> Bidiagonalized form # 1,2,3 -> Bidiagonal_decomposition matrices # 4 -> Product of 1 2 3 M = Matrix(row, col, test_values) N = ImmutableMatrix(M) N1, N2, N3 = N.bidiagonal_decomposition() M1, M2, M3 = M.bidiagonal_decomposition() M0 = M.bidiagonalize() N0 = N.bidiagonalize() N4 = N1 * N2 * N3 M4 = M1 * M2 * M3 N2.simplify() N4.simplify() N0.simplify() M0.simplify() M2.simplify() M4.simplify() LM0 = M.bidiagonalize(upper=False) LM1, LM2, LM3 = M.bidiagonal_decomposition(upper=False) LN0 = N.bidiagonalize(upper=False) LN1, LN2, LN3 = N.bidiagonal_decomposition(upper=False) LN4 = LN1 * LN2 * LN3 LM4 = LM1 * LM2 * LM3 LN2.simplify() LN4.simplify() LN0.simplify() LM0.simplify() LM2.simplify() LM4.simplify() assert M == M4 assert M2 == M0 assert N == N4 assert N2 == N0 assert M == LM4 assert LM2 == LM0 assert N == LN4 assert LN2 == LN0 #Complex Tests for complex_test in range(2): test_values = [] size = 2 for _ in range(size * size): real = random.randint(-1000000000, 1000000000) comp = random.randint(-1000000000, 1000000000) value = real + comp * I test_values = test_values + [value] M = Matrix(size, size, test_values) N = ImmutableMatrix(M) # L -> Lower Bidiagonalization # M -> Mutable Matrix # N -> Immutable Matrix # 0 -> Bidiagonalized form # 1,2,3 -> Bidiagonal_decomposition matrices # 4 -> Product of 1 2 3 N1, N2, N3 = N.bidiagonal_decomposition() M1, M2, M3 = M.bidiagonal_decomposition() M0 = M.bidiagonalize() N0 = N.bidiagonalize() N4 = N1 * N2 * N3 M4 = M1 * M2 * M3 N2.simplify() N4.simplify() N0.simplify() M0.simplify() M2.simplify() M4.simplify() LM0 = M.bidiagonalize(upper=False) LM1, LM2, LM3 = M.bidiagonal_decomposition(upper=False) LN0 = N.bidiagonalize(upper=False) LN1, LN2, LN3 = N.bidiagonal_decomposition(upper=False) LN4 = LN1 * LN2 * LN3 LM4 = LM1 * LM2 * LM3 LN2.simplify() LN4.simplify() LN0.simplify() LM0.simplify() LM2.simplify() LM4.simplify() assert M == M4 assert M2 == M0 assert N == N4 assert N2 == N0 assert M == LM4 assert LM2 == LM0 assert N == LN4 assert LN2 == LN0 M = Matrix(18, 8, range(1, 145)) M = M.applyfunc(lambda i: Float(i)) assert M.bidiagonal_decomposition()[1] == M.bidiagonalize() assert M.bidiagonal_decomposition(upper=False)[1] == M.bidiagonalize( upper=False) a, b, c = M.bidiagonal_decomposition() diff = a * b * c - M assert abs(max(diff)) < 10**-12
def test_re(): x, y = symbols('x,y') a, b = symbols('a,b', real=True) r = Symbol('r', real=True) i = Symbol('i', imaginary=True) assert re(nan) is nan assert re(oo) is oo assert re(-oo) is -oo assert re(0) == 0 assert re(1) == 1 assert re(-1) == -1 assert re(E) == E assert re(-E) == -E assert unchanged(re, x) assert re(x * I) == -im(x) assert re(r * I) == 0 assert re(r) == r assert re(i * I) == I * i assert re(i) == 0 assert re(x + y) == re(x) + re(y) assert re(x + r) == re(x) + r assert re(re(x)) == re(x) assert re(2 + I) == 2 assert re(x + I) == re(x) assert re(x + y * I) == re(x) - im(y) assert re(x + r * I) == re(x) assert re(log(2 * I)) == log(2) assert re((2 + I)**2).expand(complex=True) == 3 assert re(conjugate(x)) == re(x) assert conjugate(re(x)) == re(x) assert re(x).as_real_imag() == (re(x), 0) assert re(i * r * x).diff(r) == re(i * x) assert re(i * r * x).diff(i) == I * r * im(x) assert re( sqrt(a + b * I)) == (a**2 + b**2)**Rational(1, 4) * cos(atan2(b, a) / 2) assert re(a * (2 + b * I)) == 2 * a assert re((1 + sqrt(a + b*I))/2) == \ (a**2 + b**2)**Rational(1, 4)*cos(atan2(b, a)/2)/2 + S.Half assert re(x).rewrite(im) == x - S.ImaginaryUnit * im(x) assert (x + re(y)).rewrite(re, im) == x + y - S.ImaginaryUnit * im(y) a = Symbol('a', algebraic=True) t = Symbol('t', transcendental=True) x = Symbol('x') assert re(a).is_algebraic assert re(x).is_algebraic is None assert re(t).is_algebraic is False assert re(S.ComplexInfinity) is S.NaN n, m, l = symbols('n m l') A = MatrixSymbol('A', n, m) assert re(A) == (S.Half) * (A + conjugate(A)) A = Matrix([[1 + 4 * I, 2], [0, -3 * I]]) assert re(A) == Matrix([[1, 2], [0, 0]]) A = ImmutableMatrix([[1 + 3 * I, 3 - 2 * I], [0, 2 * I]]) assert re(A) == ImmutableMatrix([[1, 3], [0, 0]]) X = SparseMatrix([[2 * j + i * I for i in range(5)] for j in range(5)]) assert re(X) - Matrix([[0, 0, 0, 0, 0], [2, 2, 2, 2, 2], [4, 4, 4, 4, 4], [6, 6, 6, 6, 6], [8, 8, 8, 8, 8] ]) == Matrix.zeros(5) assert im(X) - Matrix([[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4] ]) == Matrix.zeros(5) X = FunctionMatrix(3, 3, Lambda((n, m), n + m * I)) assert re(X) == Matrix([[0, 0, 0], [1, 1, 1], [2, 2, 2]])
def wigner_d_small(J, beta): """Return the small Wigner d matrix for angular momentum J. Explanation =========== J : An integer, half-integer, or SymPy symbol for the total angular momentum of the angular momentum space being rotated. beta : A real number representing the Euler angle of rotation about the so-called line of nodes. See [Edmonds74]_. Returns ======= A matrix representing the corresponding Euler angle rotation( in the basis of eigenvectors of `J_z`). .. math :: \\mathcal{d}_{\\beta} = \\exp\\big( \\frac{i\\beta}{\\hbar} J_y\\big) The components are calculated using the general form [Edmonds74]_, equation 4.1.15. Examples ======== >>> from sympy import Integer, symbols, pi, pprint >>> from sympy.physics.wigner import wigner_d_small >>> half = 1/Integer(2) >>> beta = symbols("beta", real=True) >>> pprint(wigner_d_small(half, beta), use_unicode=True) ⎡ ⎛β⎞ ⎛β⎞⎤ ⎢cos⎜─⎟ sin⎜─⎟⎥ ⎢ ⎝2⎠ ⎝2⎠⎥ ⎢ ⎥ ⎢ ⎛β⎞ ⎛β⎞⎥ ⎢-sin⎜─⎟ cos⎜─⎟⎥ ⎣ ⎝2⎠ ⎝2⎠⎦ >>> pprint(wigner_d_small(2*half, beta), use_unicode=True) ⎡ 2⎛β⎞ ⎛β⎞ ⎛β⎞ 2⎛β⎞ ⎤ ⎢ cos ⎜─⎟ √2⋅sin⎜─⎟⋅cos⎜─⎟ sin ⎜─⎟ ⎥ ⎢ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎥ ⎢ ⎥ ⎢ ⎛β⎞ ⎛β⎞ 2⎛β⎞ 2⎛β⎞ ⎛β⎞ ⎛β⎞⎥ ⎢-√2⋅sin⎜─⎟⋅cos⎜─⎟ - sin ⎜─⎟ + cos ⎜─⎟ √2⋅sin⎜─⎟⋅cos⎜─⎟⎥ ⎢ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎝2⎠⎥ ⎢ ⎥ ⎢ 2⎛β⎞ ⎛β⎞ ⎛β⎞ 2⎛β⎞ ⎥ ⎢ sin ⎜─⎟ -√2⋅sin⎜─⎟⋅cos⎜─⎟ cos ⎜─⎟ ⎥ ⎣ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎝2⎠ ⎦ From table 4 in [Edmonds74]_ >>> pprint(wigner_d_small(half, beta).subs({beta:pi/2}), use_unicode=True) ⎡ √2 √2⎤ ⎢ ── ──⎥ ⎢ 2 2 ⎥ ⎢ ⎥ ⎢-√2 √2⎥ ⎢──── ──⎥ ⎣ 2 2 ⎦ >>> pprint(wigner_d_small(2*half, beta).subs({beta:pi/2}), ... use_unicode=True) ⎡ √2 ⎤ ⎢1/2 ── 1/2⎥ ⎢ 2 ⎥ ⎢ ⎥ ⎢-√2 √2 ⎥ ⎢──── 0 ── ⎥ ⎢ 2 2 ⎥ ⎢ ⎥ ⎢ -√2 ⎥ ⎢1/2 ──── 1/2⎥ ⎣ 2 ⎦ >>> pprint(wigner_d_small(3*half, beta).subs({beta:pi/2}), ... use_unicode=True) ⎡ √2 √6 √6 √2⎤ ⎢ ── ── ── ──⎥ ⎢ 4 4 4 4 ⎥ ⎢ ⎥ ⎢-√6 -√2 √2 √6⎥ ⎢──── ──── ── ──⎥ ⎢ 4 4 4 4 ⎥ ⎢ ⎥ ⎢ √6 -√2 -√2 √6⎥ ⎢ ── ──── ──── ──⎥ ⎢ 4 4 4 4 ⎥ ⎢ ⎥ ⎢-√2 √6 -√6 √2⎥ ⎢──── ── ──── ──⎥ ⎣ 4 4 4 4 ⎦ >>> pprint(wigner_d_small(4*half, beta).subs({beta:pi/2}), ... use_unicode=True) ⎡ √6 ⎤ ⎢1/4 1/2 ── 1/2 1/4⎥ ⎢ 4 ⎥ ⎢ ⎥ ⎢-1/2 -1/2 0 1/2 1/2⎥ ⎢ ⎥ ⎢ √6 √6 ⎥ ⎢ ── 0 -1/2 0 ── ⎥ ⎢ 4 4 ⎥ ⎢ ⎥ ⎢-1/2 1/2 0 -1/2 1/2⎥ ⎢ ⎥ ⎢ √6 ⎥ ⎢1/4 -1/2 ── -1/2 1/4⎥ ⎣ 4 ⎦ """ M = [J - i for i in range(2 * J + 1)] d = zeros(2 * J + 1) for i, Mi in enumerate(M): for j, Mj in enumerate(M): # We get the maximum and minimum value of sigma. sigmamax = max([-Mi - Mj, J - Mj]) sigmamin = min([0, J - Mi]) dij = sqrt( factorial(J + Mi) * factorial(J - Mi) / factorial(J + Mj) / factorial(J - Mj)) terms = [(-1)**(J - Mi - s) * binomial(J + Mj, J - Mi - s) * binomial(J - Mj, s) * cos(beta / 2)**(2 * s + Mi + Mj) * sin(beta / 2)**(2 * J - 2 * s - Mj - Mi) for s in range(sigmamin, sigmamax + 1)] d[i, j] = dij * Add(*terms) return ImmutableMatrix(d)
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(S(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, ImmutableMatrix) # 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() == ImmutableMatrix( [[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_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_im(): x, y = symbols('x,y') a, b = symbols('a,b', real=True) r = Symbol('r', real=True) i = Symbol('i', imaginary=True) assert im(nan) is nan assert im(oo * I) is oo assert im(-oo * I) is -oo assert im(0) == 0 assert im(1) == 0 assert im(-1) == 0 assert im(E * I) == E assert im(-E * I) == -E assert unchanged(im, x) assert im(x * I) == re(x) assert im(r * I) == r assert im(r) == 0 assert im(i * I) == 0 assert im(i) == -I * i assert im(x + y) == im(x) + im(y) assert im(x + r) == im(x) assert im(x + r * I) == im(x) + r assert im(im(x) * I) == im(x) assert im(2 + I) == 1 assert im(x + I) == im(x) + 1 assert im(x + y * I) == im(x) + re(y) assert im(x + r * I) == im(x) + r assert im(log(2 * I)) == pi / 2 assert im((2 + I)**2).expand(complex=True) == 4 assert im(conjugate(x)) == -im(x) assert conjugate(im(x)) == im(x) assert im(x).as_real_imag() == (im(x), 0) assert im(i * r * x).diff(r) == im(i * x) assert im(i * r * x).diff(i) == -I * re(r * x) assert im( sqrt(a + b * I)) == (a**2 + b**2)**Rational(1, 4) * sin(atan2(b, a) / 2) assert im(a * (2 + b * I)) == a * b assert im((1 + sqrt(a + b*I))/2) == \ (a**2 + b**2)**Rational(1, 4)*sin(atan2(b, a)/2)/2 assert im(x).rewrite(re) == -S.ImaginaryUnit * (x - re(x)) assert (x + im(y)).rewrite(im, re) == x - S.ImaginaryUnit * (y - re(y)) a = Symbol('a', algebraic=True) t = Symbol('t', transcendental=True) x = Symbol('x') assert re(a).is_algebraic assert re(x).is_algebraic is None assert re(t).is_algebraic is False assert im(S.ComplexInfinity) is S.NaN n, m, l = symbols('n m l') A = MatrixSymbol('A', n, m) assert im(A) == (S.One / (2 * I)) * (A - conjugate(A)) A = Matrix([[1 + 4 * I, 2], [0, -3 * I]]) assert im(A) == Matrix([[4, 0], [0, -3]]) A = ImmutableMatrix([[1 + 3 * I, 3 - 2 * I], [0, 2 * I]]) assert im(A) == ImmutableMatrix([[3, -2], [0, 2]]) X = ImmutableSparseMatrix([[i * I + i for i in range(5)] for i in range(5)]) Y = SparseMatrix([[i for i in range(5)] for i in range(5)]) assert im(X).as_immutable() == Y X = FunctionMatrix(3, 3, Lambda((n, m), n + m * I)) assert im(X) == Matrix([[0, 1, 2], [0, 1, 2], [0, 1, 2]])