def test_make_disjunct_indices(): i = IdxSym('i') j = IdxSym('j') k = IdxSym('k') def Psi(*args): return KetSymbol(StrLabel(Indexed(IndexedBase('Psi'), *args)), hs=0) def sum(term, *index_symbols): return KetIndexedSum( term, ranges=[IndexOverRange(i, 0, 2) for i in index_symbols]) with pytest.raises(ValueError): sum(Psi(i, j, j), i, j, j) expr = sum(Psi(i, j, k), i, j, k) others = [expr] expected = expr.substitute({i: i.prime, j: j.prime, k: k.prime}) expr_primed = expr.make_disjunct_indices(*others) assert expr_primed == expected others = [sum(Psi(i), i), sum(Psi(j), j)] assert expr.make_disjunct_indices(*others) == expr.substitute({ i: i.prime, j: j.prime }) others = [sum(Psi(i), i), sum(Psi(i.prime), i.prime)] assert expr.make_disjunct_indices(*others) == expr.substitute( {i: i.prime.prime})
def test_ascii_symbolic_labels(): """Test ascii representation of symbols with symbolic labels""" i = IdxSym('i') j = IdxSym('j') hs0 = LocalSpace(0) hs1 = LocalSpace(1) Psi = IndexedBase('Psi') assert ascii(BasisKet(FockIndex(2 * i), hs=hs0)) == '|2*i>^(0)' assert ascii(KetSymbol(StrLabel(2 * i), hs=hs0)) == '|2*i>^(0)' assert (ascii(KetSymbol(StrLabel(Psi[i, j]), hs=hs0 * hs1)) == '|Psi_ij>^(0*1)') expr = BasisKet(FockIndex(i), hs=hs0) * BasisKet(FockIndex(j), hs=hs1) assert ascii(expr) == '|i,j>^(0*1)' assert ascii(Bra(BasisKet(FockIndex(2 * i), hs=hs0))) == '<2*i|^(0)' assert (ascii(LocalSigma(FockIndex(i), FockIndex(j), hs=hs0)) == '|i><j|^(0)') expr = CoherentStateKet(symbols('alpha'), hs=1).to_fock_representation() assert (ascii(expr) == 'exp(-alpha*conjugate(alpha)/2) * ' '(Sum_{n in H_1} alpha**n/sqrt(n!) * |n>^(1))') tls = SpinSpace(label='s', spin='1/2', basis=('down', 'up')) Sig = IndexedBase('sigma') n = IdxSym('n') Sig_n = OperatorSymbol(StrLabel(Sig[n]), hs=tls) assert ascii(Sig_n, show_hs_label=False) == 'sigma_n'
def test_tex_symbolic_labels(): """Test tex representation of symbols with symbolic labels""" i = IdxSym('i') j = IdxSym('j') hs0 = LocalSpace(0) hs1 = LocalSpace(1) Psi = IndexedBase('Psi') with configure_printing(tex_use_braket=True): assert latex(BasisKet(FockIndex(2 * i), hs=hs0)) == r'\Ket{2 i}^{(0)}' assert latex(KetSymbol(StrLabel(2 * i), hs=hs0)) == r'\Ket{2 i}^{(0)}' assert (latex(KetSymbol(StrLabel(Psi[i, j]), hs=hs0 * hs1)) == r'\Ket{\Psi_{i j}}^{(0 \otimes 1)}') expr = BasisKet(FockIndex(i), hs=hs0) * BasisKet(FockIndex(j), hs=hs1) assert latex(expr) == r'\Ket{i,j}^{(0 \otimes 1)}' assert (latex(Bra(BasisKet(FockIndex(2 * i), hs=hs0))) == r'\Bra{2 i}^{(0)}') assert (latex(LocalSigma(FockIndex(i), FockIndex(j), hs=hs0)) == r'\Ket{i}\!\Bra{j}^{(0)}') alpha = symbols('alpha') expr = CoherentStateKet(alpha, hs=1).to_fock_representation() assert (latex(expr) == r'e^{- \frac{\alpha \overline{\alpha}}{2}} ' r'\left(\sum_{n \in \mathcal{H}_{1}} ' r'\frac{\alpha^{n}}{\sqrt{n!}} \Ket{n}^{(1)}\right)') assert (latex( expr, conjg_style='star') == r'e^{- \frac{\alpha {\alpha}^*}{2}} ' r'\left(\sum_{n \in \mathcal{H}_{1}} ' r'\frac{\alpha^{n}}{\sqrt{n!}} \Ket{n}^{(1)}\right)') tls = SpinSpace(label='s', spin='1/2', basis=('down', 'up')) Sig = IndexedBase('sigma') n = IdxSym('n') Sig_n = OperatorSymbol(StrLabel(Sig[n]), hs=tls) assert latex(Sig_n, show_hs_label=False) == r'\hat{\sigma}_{n}'
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_quantum_derivative_nonatomic_free_symbols(MyScalarFunc): """Test the free_symbols of an evaluated derivative for non-atomic symbols""" s = IndexedBase('s') t = IndexedBase('t') i = IdxSym('i') j = IdxSym('j') t0 = symbols('t_0', real=True) f = MyScalarFunc("f", s[i], t[j]) fdot = f.diff(s[i], n=2).diff(t[j]).evaluate_at({t[j]: t0}) assert fdot == fdot.__class__(f, derivs={ s[i]: 2, t[j]: 1 }, vals={t[j]: t0}) assert fdot.kwargs == OrderedDict([('derivs', ((s[i], 2), (t[j], 1))), ('vals', ((t[j], t0), ))]) assert fdot.derivs == {s[i]: 2, t[j]: 1} assert fdot.syms == {s[i], t[j]} assert fdot.vals == {t[j]: t0} assert fdot.free_symbols == set([s.args[0], s[i], i, t0]) assert fdot.bound_symbols == set([t.args[0], j, t[j]]) assert fdot.all_symbols == set( [s.args[0], t.args[0], t0, i, j, s[i], t[j]]) assert fdot.diff(s[i]).n == 4 assert fdot.diff(t[j]) == Zero f = MyScalarFunc("f", s[i], t[j], j) # additional argument j fdot = f.diff(s[i], n=2).diff(t[j]).evaluate_at({t[j]: t0}) assert fdot.free_symbols == set([s.args[0], i, j, s[i], t0]) assert fdot.bound_symbols == set([t.args[0], j, t[j]])
def test_kronecker_delta(): """Test of KroneckerDelta, in addition to the doctest""" i, j = IdxSym('i'), IdxSym('j') delta_ij = KroneckerDelta(i, j) assert isinstance(delta_ij, Scalar) assert delta_ij != Zero assert delta_ij != One assert isinstance(delta_ij.val, SympyKroneckerDelta) assert delta_ij.substitute({i: 1, j: 1}) == One assert delta_ij.substitute({i: 0, j: 1}) == Zero delta_i1 = KroneckerDelta(i, 1) assert isinstance(delta_i1, Scalar) assert delta_i1 != Zero assert delta_i1 != One assert isinstance(delta_i1.val, SympyKroneckerDelta) assert delta_i1.substitute({i: 1}) == One assert delta_i1.substitute({i: 0}) == Zero delta_1i = KroneckerDelta(1, i) assert isinstance(delta_1i, Scalar) assert delta_1i != Zero assert delta_1i != One assert isinstance(delta_1i.val, SympyKroneckerDelta) assert delta_i1.substitute({i: 1}) == One assert delta_i1.substitute({i: 0}) == Zero
def test_operator_kronecker_sum(): """Test that Kronecker delta are eliminiated from indexed sums over operators""" i = IdxSym('i') j = IdxSym('j') alpha = symbols('alpha') delta_ij = KroneckerDelta(i, j) delta_0i = KroneckerDelta(0, i) delta_1j = KroneckerDelta(1, j) delta_0j = KroneckerDelta(0, j) delta_1i = KroneckerDelta(1, i) def A(i, j): return OperatorSymbol(StrLabel(IndexedBase('A')[i, j]), hs=0) term = delta_ij * A(i, j) sum = OperatorIndexedSum.create(term, ranges=(IndexOverList(i, (1, 2)), IndexOverList(j, (1, 2)))) assert sum == OperatorIndexedSum.create(A(i, i), ranges=(IndexOverList(i, (1, 2)), )) assert sum.doit() == (OperatorSymbol("A_11", hs=0) + OperatorSymbol("A_22", hs=0)) term = alpha * delta_ij * A(i, j) range_i = IndexOverList(i, (1, 2)) range_j = IndexOverList(j, (1, 2)) sum = OperatorIndexedSum.create(term, ranges=(range_i, range_j)) assert isinstance(sum, ScalarTimesOperator) expected = alpha * OperatorIndexedSum.create( A(i, i), ranges=(IndexOverList(i, (1, 2)), )) assert sum == expected hs = LocalSpace('0', basis=('g', 'e')) i_range = IndexOverFockSpace(i, hs) j_range = IndexOverFockSpace(j, hs) sig_ij = LocalSigma(FockIndex(i), FockIndex(j), hs=hs) sig_0j = LocalSigma('g', FockIndex(j), hs=hs) sig_i1 = LocalSigma(FockIndex(i), 'e', hs=hs) term = delta_0i * delta_1j * sig_ij sum = OperatorIndexedSum.create(term, ranges=(i_range, )) expected = delta_1j * sig_0j assert sum == expected sum = OperatorIndexedSum.create(term, ranges=(j_range, )) expected = delta_0i * sig_i1 assert sum == expected term = (delta_0i * delta_1j + delta_0j * delta_1i) * sig_ij sum = OperatorIndexedSum.create(term, ranges=(i_range, j_range)) expected = LocalSigma('g', 'e', hs=hs) + LocalSigma('e', 'g', hs=hs) assert sum == expected
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_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_coherent_state(): """Test fock representation of coherent state""" alpha = symbols('alpha') hs0 = LocalSpace(0) hs1 = LocalSpace(1, dimension=3) i = IdxSym('i') n = IdxSym('n') psi = CoherentStateKet(alpha, hs=hs0) psi_focksum_3 = psi.to_fock_representation(max_terms=3) assert len(psi_focksum_3.term) == 3 for n_val in (0, 1, 2): assert n_val in psi_focksum_3.term.ranges[0] psi_focksum_inf = psi.to_fock_representation() with pytest.raises(InfiniteSumError): len(psi_focksum_inf.term) for n_val in (0, 1, 2, 3): assert n_val in psi_focksum_inf.term.ranges[0] assert psi_focksum_inf.term.term.free_symbols == set([n, symbols('alpha')]) assert psi_focksum_inf.free_symbols == set([symbols('alpha')]) assert psi_focksum_inf.term.variables == [n] assert psi_focksum_inf.substitute({n: i}).term.variables == [i] assert (psi_focksum_inf.substitute({hs0: hs1}) == CoherentStateKet( alpha, hs=hs1).to_fock_representation()) assert (psi.to_fock_representation(index_symbol='i').substitute( {i: n}) == psi_focksum_inf) assert (psi.to_fock_representation(index_symbol=i).substitute( {i: n}) == psi_focksum_inf) assert psi_focksum_3.doit([IndexedSum ]) == psi_focksum_inf.doit([IndexedSum], max_terms=3) psi_expanded_3 = psi_focksum_3.doit([IndexedSum]) assert psi_expanded_3 == ( sympy.exp(-alpha * alpha.conjugate() / 2) * KetPlus( BasisKet(0, hs=LocalSpace(0)), ScalarTimesKet(alpha, BasisKet(1, hs=LocalSpace(0))), ScalarTimesKet(alpha**2 / sympy.sqrt(2), BasisKet(2, hs=LocalSpace(0))), )) psi = CoherentStateKet(alpha, hs=hs1) assert psi.to_fock_representation().doit( [IndexedSum]) == psi_expanded_3.substitute({hs0: hs1})
def test_index_over_range_with_step(): i = IdxSym('i') r = IndexOverRange(i, 1, 10, step=2) assert len(r) == 5 assert list(r.range) == [1, 3, 5, 7, 9] for val in r.range: assert val in r assert 2 not in r assert 10 not in r
def test_index_over_range_bw(): i = IdxSym('i') r = IndexOverRange(i, 10, 1, step=-2) assert len(r) == 5 assert list(r.range) == [10, 8, 6, 4, 2] for val in r.range: assert val in r assert 5 not in r assert 1 not in r
def test_unicode_ket_operations(): """Test the unicode representation of ket operations""" hs1 = LocalSpace('q_1', basis=('g', 'e')) hs2 = LocalSpace('q_2', basis=('g', 'e')) ket_g1 = BasisKet('g', hs=hs1) ket_e1 = BasisKet('e', hs=hs1) ket_g2 = BasisKet('g', hs=hs2) ket_e2 = BasisKet('e', hs=hs2) psi1 = KetSymbol("Psi_1", hs=hs1) psi2 = KetSymbol("Psi_2", hs=hs1) phi = KetSymbol("Phi", hs=hs2) A = OperatorSymbol("A_0", hs=hs1) gamma = symbols('gamma', positive=True) alpha = symbols('alpha') beta = symbols('beta') phase = exp(-I * gamma) i = IdxSym('i') assert unicode(psi1 + psi2) == '|Ψ₁⟩^(q₁) + |Ψ₂⟩^(q₁)' assert unicode(psi1 * phi) == '|Ψ₁⟩^(q₁) ⊗ |Φ⟩^(q₂)' assert unicode(phase * psi1) == 'exp(-ⅈ γ) |Ψ₁⟩^(q₁)' assert unicode((alpha + 1) * KetSymbol('Psi', hs=0)) == '(α + 1) |Ψ⟩⁽⁰⁾' assert (unicode( A * psi1) == 'A\u0302_0^(q\u2081) |\u03a8\u2081\u27e9^(q\u2081)') # Â_0^(q₁) |Ψ₁⟩^(q₁) assert unicode(BraKet(psi1, psi2)) == '⟨Ψ₁|Ψ₂⟩^(q₁)' expr = BraKet(KetSymbol('Psi_1', alpha, hs=hs1), KetSymbol('Psi_2', beta, hs=hs1)) assert unicode(expr) == '⟨Ψ₁(α)|Ψ₂(β)⟩^(q₁)' assert unicode(ket_e1.dag() * ket_e1) == '1' assert unicode(ket_g1.dag() * ket_e1) == '0' assert unicode(KetBra(psi1, psi2)) == '|Ψ₁⟩⟨Ψ₂|^(q₁)' expr = KetBra(KetSymbol('Psi_1', alpha, hs=hs1), KetSymbol('Psi_2', beta, hs=hs1)) assert unicode(expr) == '|Ψ₁(α)⟩⟨Ψ₂(β)|^(q₁)' bell1 = (ket_e1 * ket_g2 - I * ket_g1 * ket_e2) / sqrt(2) bell2 = (ket_e1 * ket_e2 - ket_g1 * ket_g2) / sqrt(2) assert unicode(bell1) == '1/√2 (|eg⟩^(q₁⊗q₂) - ⅈ |ge⟩^(q₁⊗q₂))' assert (unicode(BraKet.create( bell1, bell2)) == r'1/2 (⟨eg|^(q₁⊗q₂) + ⅈ ⟨ge|^(q₁⊗q₂)) (|ee⟩^(q₁⊗q₂) - ' r'|gg⟩^(q₁⊗q₂))') assert (unicode(KetBra.create( bell1, bell2)) == r'1/2 (|eg⟩^(q₁⊗q₂) - ⅈ |ge⟩^(q₁⊗q₂))(⟨ee|^(q₁⊗q₂) - ' r'⟨gg|^(q₁⊗q₂))') assert (unicode( KetBra.create(bell1, bell2), show_hs_label=False) == r'1/2 (|eg⟩ - ⅈ |ge⟩)(⟨ee| - ⟨gg|)') expr = KetBra(KetSymbol('Psi', hs=0), BasisKet(FockIndex(i), hs=0)) assert unicode(expr) == "|Ψ⟩⟨i|⁽⁰⁾" expr = KetBra(BasisKet(FockIndex(i), hs=0), KetSymbol('Psi', hs=0)) assert unicode(expr) == "|i⟩⟨Ψ|⁽⁰⁾" expr = BraKet(KetSymbol('Psi', hs=0), BasisKet(FockIndex(i), hs=0)) assert unicode(expr) == "⟨Ψ|i⟩⁽⁰⁾" expr = BraKet(BasisKet(FockIndex(i), hs=0), KetSymbol('Psi', hs=0)) assert unicode(expr) == "⟨i|Ψ⟩⁽⁰⁾"
def test_tex_hilbert_elements(): """Test the tex representation of "atomic" Hilbert space algebra elements""" assert latex(LocalSpace(1)) == r'\mathcal{H}_{1}' assert latex(LocalSpace(1, dimension=2)) == r'\mathcal{H}_{1}' assert latex(LocalSpace(1, basis=(r'g', 'e'))) == r'\mathcal{H}_{1}' assert latex(LocalSpace('local')) == r'\mathcal{H}_{\text{local}}' assert latex(LocalSpace('kappa')) == r'\mathcal{H}_{\kappa}' assert latex(TrivialSpace) == r'\mathcal{H}_{\text{null}}' assert latex(FullSpace) == r'\mathcal{H}_{\text{total}}' assert latex(LocalSpace(StrLabel(IdxSym('i')))) == r'\mathcal{H}_{i}'
def test_unicode_hilbert_elements(): """Test the unicode representation of "atomic" Hilbert space algebra elements""" assert unicode(LocalSpace(1)) == 'ℌ₁' assert unicode(LocalSpace(1, dimension=2)) == 'ℌ₁' assert unicode(LocalSpace(1, basis=('g', 'e'))) == 'ℌ₁' assert unicode(LocalSpace('local')) == 'ℌ_local' assert unicode(LocalSpace('kappa')) == 'ℌ_κ' assert unicode(TrivialSpace) == 'ℌ_null' assert unicode(FullSpace) == 'ℌ_total' assert unicode(LocalSpace(StrLabel(IdxSym('i')))) == 'ℌ_i'
def test_srepr_idx_sym(): """Test the representation of IdxSym instances""" i = IdxSym('i') assert srepr(i) == "IdxSym('i', integer=True)" assert srepr(i.prime) == "IdxSym('i', integer=True, primed=1)" assert eval(srepr(i)) == i assert eval(srepr(i.prime)) == i.prime i_pos = IdxSym('i', positive=True) assert i != i_pos assert srepr(i_pos) == "IdxSym('i', integer=True, positive=True)" assert eval(srepr(i_pos)) == i_pos assert (srepr(i_pos.prime.prime) == "IdxSym('i', integer=True, positive=True, primed=2)") assert eval(srepr(i_pos.prime.prime)) == i_pos.prime.prime i_nonint = IdxSym('i', integer=False) assert i != i_nonint assert srepr(i_nonint) == "IdxSym('i', integer=False)" assert eval(srepr(i_nonint)) == i_nonint assert eval(srepr(i_nonint.prime.prime)) == i_nonint.prime.prime
def test_quantum_symbols_with_symargs(): """Test properties and behavior of symbols with scalar arguments, through the example of an OperatorSymbol""" t = IndexedBase('t') i = IdxSym('i') j = IdxSym('j') alpha, beta = symbols('alpha, beta') A = OperatorSymbol("A", t[i], (alpha + 1)**2, hs=0) assert A.label == 'A' assert len(A.args) == 3 assert A.kwargs == {'hs': LocalSpace('0')} assert A._get_instance_key(A.args, A.kwargs) == ( OperatorSymbol, 'A', t[i], (alpha + 1)**2, ('hs', A.space), ) A_beta = OperatorSymbol("A", beta, (alpha + 1)**2, hs=0) assert A != A_beta assert A.substitute({t[i]: beta}) == A_beta half = sympy.sympify(1) / 2 assert A.sym_args == (t[i], (alpha + 1)**2) assert A.free_symbols == {symbols('t'), i, t[i], alpha} assert len(A.bound_symbols) == 0 assert A.simplify_scalar(sympy.expand) == OperatorSymbol("A", t[i], alpha**2 + 2 * alpha + 1, hs=0) assert A.diff(beta) == ZeroOperator assert A.diff(t[j]) == ZeroOperator assert OperatorSymbol("A", t[i], i, j, hs=0).diff(t[j]) == ZeroOperator assert A.diff(alpha) == OperatorDerivative(A, derivs=((alpha, 1), )) assert A.expand() == A series = A.series_expand(t[i], about=beta, order=2) assert len(series) == 3 assert series[0] == OperatorSymbol("A", beta, (alpha + 1)**2, hs=0) assert series[2] == half * OperatorDerivative( A, derivs=((t[i], 2), ), vals=((t[i], beta), ))
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)
def test_ascii_hilbert_elements(): """Test the ascii representation of "atomic" Hilbert space algebra elements""" assert ascii(LocalSpace(1)) == 'H_1' assert ascii(LocalSpace(1, dimension=2)) == 'H_1' assert ascii(LocalSpace(1, basis=('g', 'e'))) == 'H_1' assert ascii(LocalSpace('local')) == 'H_local' assert ascii(LocalSpace('kappa')) == 'H_kappa' with pytest.raises(ValueError): LocalSpace(r'\kappa') assert ascii(TrivialSpace) == 'H_null' assert ascii(FullSpace) == 'H_total' assert ascii(LocalSpace(StrLabel(IdxSym('i')))) == 'H_i'
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_pull_constfactor_from_operator_sum(): """Test that a constant in pulled from a sum of operators.""" i = IdxSym('i') alpha = symbols('alpha') def A(i, j): return OperatorSymbol(StrLabel(IndexedBase('A')[i, j]), hs=0) term = alpha * A(i, i) range_i = IndexOverList(i, (1, 2)) expr = OperatorIndexedSum.create(term, ranges=(range_i, )) assert isinstance(expr, ScalarTimesOperator) assert expr.coeff == alpha assert isinstance(expr.term, OperatorIndexedSum)
def test_ascii_scalar(): """Test rendering of scalar values""" assert ascii(2) == ascii(ScalarValue(2)) == '2' ascii.printer.cache = {} # we always want 2.0 to be printed as '2'. Without this normalization, the # state of the cache might introduce non-reproducible behavior, as 2==2.0 assert ascii(2.0) == ascii(ScalarValue(2.0)) == '2' assert ascii(1j) == ascii(ScalarValue(1j)) == '1j' assert ascii('foo') == 'foo' i = IdxSym('i') alpha = IndexedBase('alpha') assert ascii(i) == ascii(ScalarValue(i)) == 'i' assert ascii(alpha[i]) == ascii(ScalarValue(alpha[i])) == 'alpha_i'
def test_abstract_taylor_series(MyScalarFunc): """Test a series expansion that is the abstract Taylor series only""" s = IndexedBase('s') t = IndexedBase('t') i = IdxSym('i') j = IdxSym('j') t0 = symbols('t_0', real=True) f = MyScalarFunc("f", s[i], t[j]) series = f.series_expand(t[j], about=0, order=3) assert isinstance(series[0], MyScalarFunc) assert isinstance(series[1], QuantumDerivative) assert isinstance(series[2], ScalarTimes) D = series[1].__class__ assert series[0] == MyScalarFunc("f", s[i], 0) assert series[1] == D(f, derivs={t[j]: 1}, vals={t[j]: 0}) assert series[2] == D(f, derivs={t[j]: 2}, vals={t[j]: 0}) / 2 assert series[3] == D(f, derivs={t[j]: 3}, vals={t[j]: 0}) / 6 series = f.series_expand(t[j], about=t0, order=3) assert series[0] == MyScalarFunc("f", s[i], t0) assert series[1] == D(f, derivs={t[j]: 1}, vals={t[j]: t0}) assert series[2] == D(f, derivs={t[j]: 2}, vals={t[j]: t0}) / 2 assert series[3] == D(f, derivs={t[j]: 3}, vals={t[j]: t0}) / 6
def test_unicode_symbolic_labels(): """Test unicode representation of symbols with symbolic labels""" i = IdxSym('i') j = IdxSym('j') hs0 = LocalSpace(0) hs1 = LocalSpace(1) Psi = IndexedBase('Psi') assert unicode(BasisKet(FockIndex(2 * i), hs=hs0)) == '|2 i⟩⁽⁰⁾' assert unicode(KetSymbol(StrLabel(2 * i), hs=hs0)) == '|2 i⟩⁽⁰⁾' assert (unicode(KetSymbol(StrLabel(Psi[i, j]), hs=hs0 * hs1)) == '|Ψ_ij⟩^(0⊗1)') expr = BasisKet(FockIndex(i), hs=hs0) * BasisKet(FockIndex(j), hs=hs1) assert unicode(expr) == '|i,j⟩^(0⊗1)' assert unicode(Bra(BasisKet(FockIndex(2 * i), hs=hs0))) == '⟨2 i|⁽⁰⁾' assert (unicode(LocalSigma(FockIndex(i), FockIndex(j), hs=hs0)) == '|i⟩⟨j|⁽⁰⁾') expr = CoherentStateKet(symbols('alpha'), hs=1).to_fock_representation() assert unicode(expr) == 'exp(-α α ⃰/2) (∑_{n ∈ ℌ₁} αⁿ/√n! |n⟩⁽¹⁾)' tls = SpinSpace(label='s', spin='1/2', basis=('down', 'up')) Sig = IndexedBase('sigma') n = IdxSym('n') Sig_n = OperatorSymbol(StrLabel(Sig[n]), hs=tls) assert unicode(Sig_n, show_hs_label=False) == 'σ̂ₙ'
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_indexed_sum_over_kronecker_scalarvalue(): """Test indexed_sum_over_kronecker for a ScalarValue. This is an auxiliary test to resolve a bug in test_tls_norm """ i = IdxSym('i') ip = i.prime term = KroneckerDelta(i, ip) / 2 assert isinstance(term, ScalarValue) hs = LocalSpace('tls', dimension=2) i_range = IndexOverFockSpace(i, hs) ip_range = IndexOverFockSpace(ip, hs) sum = indexed_sum_over_kronecker( ScalarIndexedSum, ops=(term,), kwargs=dict(ranges=(i_range, ip_range)), ) assert sum == 1
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_unicode_scalar(): """Test rendering of scalar values""" assert unicode(2) == '2' # we always want 2.0 to be printed as '2'. Without this normalization, the # state of the cache might introduce non-reproducible behavior, as 2==2.0 unicode.printer.cache = {} assert 2 == 2.0 assert unicode(2.0) == '2' # would be '2.0' without normalization assert unicode(1j) == '1j' assert ((I / 2) - 0.5j) == 0 assert unicode(I / 2) == 'ⅈ/2' assert unicode(0.5j) == '0.5j' assert unicode(sympy.pi) == 'π' assert unicode(sympy.pi / 4) == 'π/4' i = IdxSym('i') alpha = IndexedBase('alpha') assert unicode(alpha[i]) == 'α_i' assert unicode(alpha[1]) == 'α₁'
def test_invalid_spin_space(): """Test that a ValueError is raised when trying to instantiate a SpinSpace with and invalid `spin` value""" with pytest.raises(ValueError) as exc_info: SpinSpace(0, spin=0) assert "must be greater than zero" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: SpinSpace(0, spin=-1) assert "must be greater than zero" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: SpinSpace(0, spin=sympy.Rational(2, 3)) assert "must be an integer or half-integer" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: SpinSpace(0, spin="one") assert "must be an integer or half-integer" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: SpinSpace(0, spin=IdxSym('i')) assert "must be an integer or half-integer" in str(exc_info.value) with pytest.raises(TypeError) as exc_info: SpinSpace(0) assert "required keyword-only argument: 'spin'" in str(exc_info.value)
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