def test_sum_instantiator(): """Test use of Sum instantiator.""" i = IdxSym('i') j = IdxSym('j') ket_i = BasisKet(FockIndex(i), hs=0) ket_j = BasisKet(FockIndex(j), hs=0) A_i = OperatorSymbol(StrLabel(IndexedBase('A')[i]), hs=0) hs0 = LocalSpace('0') sum = Sum(i)(ket_i) ful = KetIndexedSum(ket_i, ranges=IndexOverFockSpace(i, hs=hs0)) assert sum == ful assert sum == Sum(i, hs0)(ket_i) assert sum == Sum(i, hs=hs0)(ket_i) sum = Sum(i, 1, 10)(ket_i) ful = KetIndexedSum(ket_i, ranges=IndexOverRange(i, 1, 10)) assert sum == ful assert sum == Sum(i, 1, 10, 1)(ket_i) assert sum == Sum(i, 1, to=10, step=1)(ket_i) assert sum == Sum(i, 1, 10, step=1)(ket_i) sum = Sum(i, (1, 2, 3))(ket_i) ful = KetIndexedSum(ket_i, ranges=IndexOverList(i, (1, 2, 3))) assert sum == KetIndexedSum(ket_i, ranges=IndexOverList(i, (1, 2, 3))) assert sum == Sum(i, [1, 2, 3])(ket_i) sum = Sum(i)(Sum(j)(ket_i * ket_j.dag())) ful = OperatorIndexedSum( ket_i * ket_j.dag(), ranges=(IndexOverFockSpace(i, hs0), IndexOverFockSpace(j, hs0)), ) assert sum == ful
def test_qubit_state_bra(): """Test sum_i alpha_i <i| for TLS""" i = IdxSym('i') alpha = IndexedBase('alpha') alpha_i = alpha[i] hs_tls = LocalSpace('tls', basis=('g', 'e')) term = alpha_i * BasisKet(FockIndex(i), hs=hs_tls).dag() expr = KetIndexedSum.create(term, ranges=IndexOverFockSpace(i, hs=hs_tls)) assert IndexOverFockSpace(i, hs=hs_tls) in expr.ket.kwargs['ranges'] assert ascii(expr) == "Sum_{i in H_tls} alpha_i * <i|^(tls)" assert expr.ket.term.free_symbols == set([i, symbols('alpha'), alpha_i]) assert expr.free_symbols == set([symbols('alpha'), alpha_i]) assert expr.ket.variables == [i] assert expr.space == hs_tls assert len(expr.ket.args) == 1 assert len(expr.ket.operands) == 1 assert len(expr.ket.kwargs) == 1 assert expr.ket.args[0] == term.ket assert expr.ket.term == term.ket assert len(expr.kwargs) == 0 expr_expand = Bra.create(expr.ket.doit().substitute({ alpha[0]: alpha['g'], alpha[1]: alpha['e'] })) assert expr_expand == (alpha['g'] * BasisKet('g', hs=hs_tls).dag() + alpha['e'] * BasisKet('e', hs=hs_tls).dag()) assert ascii(expr_expand) == 'alpha_e * <e|^(tls) + alpha_g * <g|^(tls)'
def test_ketbra_indexed_sum(): """Test ketbra product of sums""" i = IdxSym('i') hs = LocalSpace(1, dimension=5) alpha = IndexedBase('alpha') psi = KetSymbol('Psi', hs=hs) psi1 = KetIndexedSum( alpha[1, i] * BasisKet(FockIndex(i), hs=hs), ranges=IndexOverFockSpace(i, hs), ) psi2 = KetIndexedSum( alpha[2, i] * BasisKet(FockIndex(i), hs=hs), ranges=IndexOverFockSpace(i, hs), ) expr = psi1 * psi2.dag() assert expr.space == hs expected = OperatorIndexedSum( alpha[2, i.prime].conjugate() * alpha[1, i] * KetBra.create(BasisKet(FockIndex(i), hs=hs), BasisKet(FockIndex(i.prime), hs=hs)), ranges=(IndexOverFockSpace(i, hs), IndexOverFockSpace(i.prime, hs)), ) assert expr == expected assert KetBra.create(psi1, psi2) == expr expr = psi * psi2.dag() assert expr.space == hs expected = OperatorIndexedSum( alpha[2, i].conjugate() * KetBra.create(psi, BasisKet(FockIndex(i), hs=hs)), ranges=IndexOverFockSpace(i, hs), ) assert expr == expected assert KetBra.create(psi, psi2) == expr expr = psi1 * psi.dag() assert expr.space == hs expected = OperatorIndexedSum( alpha[1, i] * KetBra.create(BasisKet(FockIndex(i), hs=hs), psi), ranges=IndexOverFockSpace(i, hs), ) assert expr == expected assert KetBra.create(psi1, psi) == expr
def test_ket_indexed_sum_simplify_scalar(): """Test calling the simplify_scalar method of an KetIndexedSum.""" # This tests originates from some broken behavior when IndexedSum received # `ranges` as a positional argument instead of a keyword argument. a, b, ϕ = symbols('a, b, phi') factor = (a + b) * sympy.exp(I * ϕ) factor_expand = factor.expand() hs = LocalSpace(0) n = symbols('n', cls=IdxSym) psi_n = hs.basis_state(FockIndex(n)) expr = KetIndexedSum(factor * psi_n, ranges=(IndexOverFockSpace(n, hs=hs), )) expr_expand = expr.simplify_scalar(sympy.expand) expected = factor_expand * KetIndexedSum( psi_n, ranges=(IndexOverFockSpace(n, hs=hs), )) assert expr_expand != expected.term # happened when ranges was an argument assert expr_expand == expected
def test_create_on_fock_expansion(): """Test ``Create * sum_i alpha_i |i> = sqrt(i+1) * alpha_i * |i+1>``""" i = IdxSym('i') alpha = IndexedBase('alpha') hs = LocalSpace('0', dimension=3) expr = Create(hs=hs) * KetIndexedSum( alpha[i] * BasisKet(FockIndex(i), hs=hs), ranges=IndexOverFockSpace(i, hs), ) assert expr == KetIndexedSum( sympy.sqrt(i + 1) * alpha[i] * BasisKet(FockIndex(i + 1), hs=hs), ranges=IndexOverFockSpace(i, hs), ) assert expr.doit() == (alpha[0] * BasisKet(1, hs=hs) + sympy.sqrt(2) * alpha[1] * BasisKet(2, hs=hs))
def test_braket_indexed_sum(): """Test braket product of sums""" i = IdxSym('i') hs = LocalSpace(1, dimension=5) alpha = IndexedBase('alpha') psi = KetSymbol('Psi', hs=hs) psi1 = KetIndexedSum( alpha[1, i] * BasisKet(FockIndex(i), hs=hs), ranges=IndexOverFockSpace(i, hs), ) psi2 = KetIndexedSum( alpha[2, i] * BasisKet(FockIndex(i), hs=hs), ranges=IndexOverFockSpace(i, hs), ) expr = Bra.create(psi1) * psi2 assert expr.space == TrivialSpace assert expr == ScalarIndexedSum.create( alpha[1, i].conjugate() * alpha[2, i], ranges=(IndexOverFockSpace(i, hs), ), ) assert BraKet.create(psi1, psi2) == expr expr = psi.dag() * psi2 assert expr == ScalarIndexedSum( alpha[2, i] * BraKet(psi, BasisKet(FockIndex(i), hs=hs)), ranges=IndexOverFockSpace(i, hs), ) assert BraKet.create(psi, psi2) == expr expr = psi1.dag() * psi assert expr == ScalarIndexedSum( alpha[1, i].conjugate() * BraKet(BasisKet(FockIndex(i), hs=hs), psi), ranges=IndexOverFockSpace(i, hs), ) assert BraKet.create(psi1, psi) == expr
def test_tls_norm(): """Test that calculating the norm of a TLS state results in 1""" hs = LocalSpace('tls', dimension=2) i = IdxSym('i') ket_i = BasisKet(FockIndex(i), hs=hs) nrm = BraKet.create(ket_i, ket_i) assert nrm == 1 psi = KetIndexedSum((1 / sympy.sqrt(2)) * ket_i, ranges=IndexOverFockSpace(i, hs)) nrm = BraKet.create(psi, psi) assert nrm == 1
def test_tensor_indexed_sum(): """Test tensor product of sums""" i = IdxSym('i') hs1 = LocalSpace(1) hs2 = LocalSpace(2) alpha = IndexedBase('alpha') psi1 = KetIndexedSum( alpha[1, i] * BasisKet(FockIndex(i), hs=hs1), ranges=IndexOverFockSpace(i, hs1), ) psi2 = KetIndexedSum( alpha[2, i] * BasisKet(FockIndex(i), hs=hs2), ranges=IndexOverFockSpace(i, hs2), ) expr = psi1 * psi2 assert expr.space == hs1 * hs2 rhs = KetIndexedSum( alpha[1, i] * alpha[2, i.prime] * (BasisKet(FockIndex(i), hs=hs1) * BasisKet(FockIndex(i.prime), hs=hs2)), ranges=(IndexOverFockSpace(i, hs1), IndexOverFockSpace(i.prime, hs2)), ) assert expr == rhs psi0 = KetSymbol('Psi', hs=0) psi3 = KetSymbol('Psi', hs=3) expr2 = psi0 * psi1 * psi2 * psi3 rhs = KetIndexedSum( alpha[1, i] * alpha[2, i.prime] * (psi0 * BasisKet(FockIndex(i), hs=hs1) * BasisKet(FockIndex(i.prime), hs=hs2) * psi3), ranges=(IndexOverFockSpace(i, hs1), IndexOverFockSpace(i.prime, hs2)), ) assert expr2 == rhs assert TensorKet.create(psi0, psi1, psi2, psi3) == expr2
def test_two_hs_symbol_sum(): """Test sum_{ij} a_{ij} Psi_{ij}""" i = IdxSym('i') j = IdxSym('j') a = IndexedBase('a') hs1 = LocalSpace('1', dimension=3) hs2 = LocalSpace('2', dimension=3) hs = hs1 * hs2 Psi = IndexedBase('Psi') a_ij = a[i, j] Psi_ij = Psi[i, j] KetPsi_ij = KetSymbol(StrLabel(Psi_ij), hs=hs) term = a_ij * KetPsi_ij expr1 = KetIndexedSum( term, ranges=(IndexOverFockSpace(i, hs=hs1), IndexOverFockSpace(j, hs=hs2)), ) expr2 = KetIndexedSum(term, ranges=(IndexOverRange(i, 0, 2), IndexOverRange(j, 0, 2))) assert expr1.term.free_symbols == set( [i, j, symbols('a'), symbols('Psi'), a_ij, Psi_ij]) assert expr1.free_symbols == set( [symbols('a'), symbols('Psi'), a_ij, Psi_ij]) assert expr1.variables == [i, j] assert ( ascii(expr1) == 'Sum_{i in H_1} Sum_{j in H_2} a_ij * |Psi_ij>^(1*2)') assert unicode(expr1) == '∑_{i ∈ ℌ₁} ∑_{j ∈ ℌ₂} a_ij |Ψ_ij⟩^(1⊗2)' assert (latex(expr1) == r'\sum_{i \in \mathcal{H}_{1}} \sum_{j \in \mathcal{H}_{2}} ' r'a_{i j} \left\lvert \Psi_{i j} \right\rangle^{(1 \otimes 2)}') assert ascii(expr2) == 'Sum_{i,j=0}^{2} a_ij * |Psi_ij>^(1*2)' assert unicode(expr2) == '∑_{i,j=0}^{2} a_ij |Ψ_ij⟩^(1⊗2)' assert (latex(expr2) == r'\sum_{i,j=0}^{2} a_{i j} ' r'\left\lvert \Psi_{i j} \right\rangle^{(1 \otimes 2)}') assert expr1.doit() == expr2.doit() assert expr1.doit() == KetPlus( a[0, 0] * KetSymbol('Psi_00', hs=hs), a[0, 1] * KetSymbol('Psi_01', hs=hs), a[0, 2] * KetSymbol('Psi_02', hs=hs), a[1, 0] * KetSymbol('Psi_10', hs=hs), a[1, 1] * KetSymbol('Psi_11', hs=hs), a[1, 2] * KetSymbol('Psi_12', hs=hs), a[2, 0] * KetSymbol('Psi_20', hs=hs), a[2, 1] * KetSymbol('Psi_21', hs=hs), a[2, 2] * KetSymbol('Psi_22', hs=hs), )
def test_scalar_indexed_sum(braket): """Test instantiation and behavior of a ScalarIndexedSum""" i = IdxSym('i') ip = i.prime ipp = ip.prime alpha = IndexedBase('alpha') a = symbols('a') hs = LocalSpace(0) ket_sum = KetIndexedSum( alpha[1, i] * BasisKet(FockIndex(i), hs=hs), ranges=(IndexOverRange(i, 1, 2), ), ) bra = KetSymbol('Psi', hs=hs).dag() expr = bra * ket_sum half = sympify(1) / 2 assert isinstance(expr, ScalarIndexedSum) assert isinstance(expr.term, ScalarTimes) assert expr.term == bra * ket_sum.term assert expr.ranges == ket_sum.ranges assert expr.doit() == (alpha[1, 1] * bra * BasisKet(1, hs=hs) + alpha[1, 2] * bra * BasisKet(2, hs=hs)) expr = ScalarIndexedSum.create(i, ranges=(IndexOverRange(i, 1, 2), )) assert expr == ScalarIndexedSum(i, ranges=(IndexOverRange(i, 1, 2), )) assert isinstance(expr.doit(), ScalarValue) assert expr.doit() == 3 assert expr.real == expr assert expr.imag == Zero assert expr.conjugate() == expr assert 3 * expr == expr * 3 == Sum(i, 1, 2)(3 * i) assert a * expr == expr * a == Sum(i, 1, 2)(a * i) assert braket * expr == ScalarTimes(braket, Sum(i, 1, 2)(i)) assert expr * braket == ScalarTimes(braket, Sum(i, 1, 2)(i)) assert (2 * i) * expr == 2 * expr * i assert (2 * i) * expr == Sum(i, 1, 2)(2 * i * i.prime) assert expr * expr == ScalarIndexedSum( ScalarValue(i * ip), ranges=(IndexOverRange(i, 1, 2), IndexOverRange(ip, 1, 2)), ) sum3 = expr**3 assert sum3 == ScalarIndexedSum( ScalarValue(i * ip * ipp), ranges=( IndexOverRange(i, 1, 2), IndexOverRange(ip, 1, 2), IndexOverRange(ipp, 1, 2), ), ) assert expr**0 is One assert expr**1 is expr assert (expr**alpha).exp == alpha assert expr**-1 == 1 / expr assert (1 / expr).exp == -1 assert (expr**-alpha).exp == -alpha sqrt_sum = sqrt(expr) assert sqrt_sum == ScalarPower(expr, ScalarValue(half)) expr = ScalarIndexedSum.create(I * i, ranges=(IndexOverRange(i, 1, 2), )) assert expr.real == Zero assert expr.imag == ScalarIndexedSum.create(i, ranges=(IndexOverRange( i, 1, 2), )) assert expr.conjugate() == -expr
), # State Algebra # ... ( KetIndexedSum, 'R001', (KetSymbol(StrLabel(i), hs=0) - KetSymbol(StrLabel(i), hs=0), ), dict(ranges=(IndexOverFockSpace(i, hs=LocalSpace(0)), )), ZeroKet, ), ( KetIndexedSum, 'R002', (symbols('a') * BasisKet(FockIndex(i), hs=0), ), dict(ranges=(IndexOverRange(i, 0, 1), )), symbols('a') * KetIndexedSum(BasisKet(FockIndex(i), hs=0), ranges=(IndexOverRange(i, 0, 1), )), ), ] @pytest.mark.parametrize("cls, rule, args, kwargs, expected", TESTS) def test_rule(cls, rule, args, kwargs, expected, caplog): """Check that for the given `cls` and `rule` name (which must be a key in ``cls._rules`` or ``cls._binary_rules``), if we instantiate ``cls(*args, **kwargs)``, `rule` is applied and we obtain the `expected` result. In order to review the log of how all test expressions are created, call ``py.test`` as:: py.test -s --log-cli-level DEBUG ./tests/algebra/test_rules.py
def test_qubit_state(): """Test sum_i alpha_i |i> for TLS""" i = IdxSym('i') alpha = IndexedBase('alpha') alpha_i = alpha[i] hs_tls = LocalSpace('tls', basis=('g', 'e')) term = alpha_i * BasisKet(FockIndex(i), hs=hs_tls) expr1 = KetIndexedSum.create(term, ranges=IndexOverFockSpace(i, hs=hs_tls)) expr2 = KetIndexedSum.create(term, ranges=IndexOverList(i, [0, 1])) expr3 = KetIndexedSum.create(term, ranges=IndexOverRange(i, start_from=0, to=1)) assert IndexOverFockSpace(i, hs=hs_tls) in expr1.kwargs['ranges'] assert ascii(expr1) == "Sum_{i in H_tls} alpha_i * |i>^(tls)" assert unicode(expr1) == "∑_{i ∈ ℌ_tls} α_i |i⟩⁽ᵗˡˢ⁾" assert ( srepr(expr1) == "KetIndexedSum(ScalarTimesKet(ScalarValue(Indexed(IndexedBase(Symbol('alpha')), IdxSym('i', integer=True))), BasisKet(FockIndex(IdxSym('i', integer=True)), hs=LocalSpace('tls', basis=('g', 'e')))), ranges=(IndexOverFockSpace(IdxSym('i', integer=True), LocalSpace('tls', basis=('g', 'e'))),))" ) with configure_printing(tex_use_braket=True): assert (latex(expr1) == r'\sum_{i \in \mathcal{H}_{tls}} \alpha_{i} \Ket{i}^{(tls)}') assert ascii(expr2) == 'Sum_{i in {0,1}} alpha_i * |i>^(tls)' assert unicode(expr2) == '∑_{i ∈ {0,1}} α_i |i⟩⁽ᵗˡˢ⁾' assert ( srepr(expr2) == "KetIndexedSum(ScalarTimesKet(ScalarValue(Indexed(IndexedBase(Symbol('alpha')), IdxSym('i', integer=True))), BasisKet(FockIndex(IdxSym('i', integer=True)), hs=LocalSpace('tls', basis=('g', 'e')))), ranges=(IndexOverList(IdxSym('i', integer=True), (0, 1)),))" ) with configure_printing(tex_use_braket=True): assert ( latex(expr2) == r'\sum_{i \in \{0,1\}} \alpha_{i} \Ket{i}^{(tls)}') assert ascii(expr3) == 'Sum_{i=0}^{1} alpha_i * |i>^(tls)' assert unicode(expr3) == '∑_{i=0}^{1} α_i |i⟩⁽ᵗˡˢ⁾' assert ( srepr(expr3) == "KetIndexedSum(ScalarTimesKet(ScalarValue(Indexed(IndexedBase(Symbol('alpha')), IdxSym('i', integer=True))), BasisKet(FockIndex(IdxSym('i', integer=True)), hs=LocalSpace('tls', basis=('g', 'e')))), ranges=(IndexOverRange(IdxSym('i', integer=True), 0, 1),))" ) with configure_printing(tex_use_braket=True): assert latex(expr3) == r'\sum_{i=0}^{1} \alpha_{i} \Ket{i}^{(tls)}' for expr in (expr1, expr2, expr3): assert expr.term.free_symbols == set([i, symbols('alpha'), alpha_i]) assert expr.term.bound_symbols == set() assert expr.free_symbols == set([symbols('alpha'), alpha_i]) assert expr.variables == [i] assert expr.bound_symbols == set([i]) assert len(expr) == len(expr.ranges[0]) == 2 assert 0 in expr.ranges[0] assert 1 in expr.ranges[0] assert expr.space == hs_tls assert len(expr.args) == 1 assert len(expr.kwargs) == 1 assert len(expr.operands) == 1 assert expr.args[0] == term assert expr.term == term expr_expand = expr.doit().substitute({ alpha[0]: alpha['g'], alpha[1]: alpha['e'] }) assert expr_expand == (alpha['g'] * BasisKet('g', hs=hs_tls) + alpha['e'] * BasisKet('e', hs=hs_tls)) assert ( ascii(expr_expand) == 'alpha_e * |e>^(tls) + alpha_g * |g>^(tls)') with pytest.raises(TypeError) as exc_info: KetIndexedSum.create(alpha_i * BasisKet(i, hs=hs_tls), IndexOverFockSpace(i, hs=hs_tls)) assert "label_or_index must be an instance of" in str(exc_info.value)
def sum(term, *index_symbols): return KetIndexedSum( term, ranges=[IndexOverRange(i, 0, 2) for i in index_symbols])
def test_partial_expansion(): """Test partially executing the sum (only for a subset of summation indices)""" i = IdxSym('i') j = IdxSym('j') k = IdxSym('k') hs = LocalSpace('0', dimension=2) Psi = IndexedBase('Psi') def r(index_symbol): return IndexOverFockSpace(index_symbol, hs=hs) psi_ijk = KetSymbol(StrLabel(Psi[i, j, k]), hs=hs) def psi(i_val, j_val, k_val): return psi_ijk.substitute({i: i_val, j: j_val, k: k_val}) expr = KetIndexedSum(psi_ijk, ranges=(r(i), r(j), r(k))) expr_expanded = expr.doit(indices=[i]) assert expr_expanded == KetIndexedSum(psi(0, j, k) + psi(1, j, k), ranges=(r(j), r(k))) expr_expanded = expr.doit(indices=[j]) assert expr_expanded == KetIndexedSum(psi(i, 0, k) + psi(i, 1, k), ranges=(r(i), r(k))) assert expr.doit(indices=[j]) == expr.doit(indices=['j']) expr_expanded = expr.doit(indices=[i, j]) assert expr_expanded == KetIndexedSum(psi(0, 0, k) + psi(1, 0, k) + psi(0, 1, k) + psi(1, 1, k), ranges=r(k)) assert expr.doit(indices=[i, j]) == expr.doit(indices=[j, i]) assert expr.doit(indices=[i, j, k]) == expr.doit() with pytest.raises(ValueError): expr.doit(indices=[i], max_terms=10)