def _eval_trace(self, **kwargs): indices = kwargs.get('indices', []) return Tr(self.doit(), indices).doit()
def test_Tr(): A, B = symbols('A B', commutative=False) t = Tr(A * B) assert str(t) == 'Tr(A*B)'
def test_doit(): x, y = symbols('x y') A, B, C, D, E, F = symbols('A B C D E F', commutative=False) d = Density([XKet(), 0.5], [PxKet(), 0.5]) assert (0.5 * (PxKet() * Dagger(PxKet())) + 0.5 * (XKet() * Dagger(XKet()))) == d.doit() # check for kets with expr in them d_with_sym = Density([XKet(x * y), 0.5], [PxKet(x * y), 0.5]) assert (0.5 * (PxKet(x * y) * Dagger(PxKet(x * y))) + 0.5 * (XKet(x * y) * Dagger(XKet(x * y)))) == d_with_sym.doit() d = Density([(A + B) * C, 1.0]) assert d.doit() == (1.0 * A * C * Dagger(C) * Dagger(A) + 1.0 * A * C * Dagger(C) * Dagger(B) + 1.0 * B * C * Dagger(C) * Dagger(A) + 1.0 * B * C * Dagger(C) * Dagger(B)) # With TensorProducts as args # Density with simple tensor products as args t = TensorProduct(A, B, C) d = Density([t, 1.0]) assert d.doit() == \ 1.0 * TensorProduct(A*Dagger(A), B*Dagger(B), C*Dagger(C)) # Density with multiple Tensorproducts as states t2 = TensorProduct(A, B) t3 = TensorProduct(C, D) d = Density([t2, 0.5], [t3, 0.5]) assert d.doit() == (0.5 * TensorProduct(A * Dagger(A), B * Dagger(B)) + 0.5 * TensorProduct(C * Dagger(C), D * Dagger(D))) #Density with mixed states d = Density([t2 + t3, 1.0]) assert d.doit() == (1.0 * TensorProduct(A * Dagger(A), B * Dagger(B)) + 1.0 * TensorProduct(A * Dagger(C), B * Dagger(D)) + 1.0 * TensorProduct(C * Dagger(A), D * Dagger(B)) + 1.0 * TensorProduct(C * Dagger(C), D * Dagger(D))) #Density operators with spin states tp1 = TensorProduct(JzKet(1, 1), JzKet(1, -1)) d = Density([tp1, 1]) # full trace t = Tr(d) assert t.doit() == 1 #Partial trace on density operators with spin states t = Tr(d, [0]) assert t.doit() == JzKet(1, -1) * Dagger(JzKet(1, -1)) t = Tr(d, [1]) assert t.doit() == JzKet(1, 1) * Dagger(JzKet(1, 1)) # with another spin state tp2 = TensorProduct(JzKet(S(1) / 2, S(1) / 2), JzKet(S(1) / 2, -S(1) / 2)) d = Density([tp2, 1]) #full trace t = Tr(d) assert t.doit() == 1 #Partial trace on density operators with spin states t = Tr(d, [0]) assert t.doit() == JzKet(S(1) / 2, -S(1) / 2) * Dagger( JzKet(S(1) / 2, -S(1) / 2)) t = Tr(d, [1]) assert t.doit() == JzKet(S(1) / 2, S(1) / 2) * Dagger(JzKet(S(1) / 2, S(1) / 2))
def test_Tr(): #TODO: Handle indices A, B = symbols('A B', commutative=False) t = Tr(A * B) assert latex(t) == r'\mbox{Tr}\left(A B\right)'
def test_eval_trace(): # This test includes tests with dependencies between TensorProducts #and density operators. Since, the test is more to test the behavior of #TensorProducts it remains here A, B, C, D, E, F = symbols('A B C D E F', commutative=False) # Density with simple tensor products as args t = TensorProduct(A, B) d = Density([t, 1.0]) tr = Tr(d) assert tr.doit() == 1.0 * Tr(A * Dagger(A)) * Tr(B * Dagger(B)) ## partial trace with simple tensor products as args t = TensorProduct(A, B, C) d = Density([t, 1.0]) tr = Tr(d, [1]) assert tr.doit() == 1.0 * A * Dagger(A) * Tr(B * Dagger(B)) * C * Dagger(C) tr = Tr(d, [0, 2]) assert tr.doit() == 1.0 * Tr(A * Dagger(A)) * B * Dagger(B) * Tr( C * Dagger(C)) # Density with multiple Tensorproducts as states t2 = TensorProduct(A, B) t3 = TensorProduct(C, D) d = Density([t2, 0.5], [t3, 0.5]) t = Tr(d) assert t.doit() == (0.5 * Tr(A * Dagger(A)) * Tr(B * Dagger(B)) + 0.5 * Tr(C * Dagger(C)) * Tr(D * Dagger(D))) t = Tr(d, [0]) assert t.doit() == (0.5 * Tr(A * Dagger(A)) * B * Dagger(B) + 0.5 * Tr(C * Dagger(C)) * D * Dagger(D)) #Density with mixed states d = Density([t2 + t3, 1.0]) t = Tr(d) assert t.doit() == (1.0 * Tr(A * Dagger(A)) * Tr(B * Dagger(B)) + 1.0 * Tr(A * Dagger(C)) * Tr(B * Dagger(D)) + 1.0 * Tr(C * Dagger(A)) * Tr(D * Dagger(B)) + 1.0 * Tr(C * Dagger(C)) * Tr(D * Dagger(D))) t = Tr(d, [1]) assert t.doit() == (1.0 * A * Dagger(A) * Tr(B * Dagger(B)) + 1.0 * A * Dagger(C) * Tr(B * Dagger(D)) + 1.0 * C * Dagger(A) * Tr(D * Dagger(B)) + 1.0 * C * Dagger(C) * Tr(D * Dagger(D)))
def test_trace_new(): a, b, c, d, Y = symbols("a b c d Y") A, B, C, D = symbols("A B C D", commutative=False) assert Tr(a + b) == a + b assert Tr(A + B) == Tr(A) + Tr(B) # check trace args not implicitly permuted assert Tr(C * D * A * B).args[0].args == (C, D, A, B) # check for mul and adds assert Tr((a * b) + (c * d)) == (a * b) + (c * d) # Tr(scalar*A) = scalar*Tr(A) assert Tr(a * A) == a * Tr(A) assert Tr(a * A * B * b) == a * b * Tr(A * B) # since A is symbol and not commutative assert isinstance(Tr(A), Tr) # POW assert Tr(pow(a, b)) == a**b assert isinstance(Tr(pow(A, a)), Tr) # Matrix M = Matrix([[1, 1], [2, 2]]) assert Tr(M) == 3 ##test indices in different forms # no index t = Tr(A) assert t.args[1] == Tuple() # single index t = Tr(A, 0) assert t.args[1] == Tuple(0) # index in a list t = Tr(A, [0]) assert t.args[1] == Tuple(0) t = Tr(A, [0, 1, 2]) assert t.args[1] == Tuple(0, 1, 2) # index is tuple t = Tr(A, (0)) assert t.args[1] == Tuple(0) t = Tr(A, (1, 2)) assert t.args[1] == Tuple(1, 2) # trace indices test t = Tr((A + B), [2]) assert t.args[0].args[1] == Tuple(2) and t.args[1].args[1] == Tuple(2) t = Tr(a * A, [2, 3]) assert t.args[1].args[1] == Tuple(2, 3) # class with trace method defined # to simulate numpy objects class Foo: def trace(self): return 1 assert Tr(Foo()) == 1 # argument test # check for value error, when either/both arguments are not provided raises(ValueError, lambda: Tr()) raises(ValueError, lambda: Tr(A, 1, 2))