Lewati ke konten utama
Proyek ini masih dalam tahap beta. Menemukan bug? Buat isu GitHub. Punya pertanyaan atau ide? Tanya di Discussions — kami sangat menghargai masukan kamu!
Bagaimana kualitas terjemahan di halaman ini?

Mengelompokkan suku operator: manfaatkan struktur operator

Sebuah BosonOperator bisa menandai setiap sukunya dengan indeks grup. Tag itu tidak membawa makna sendiri: ia hanya menyatakan suku mana yang saling terkait. Apa arti tag itu ditentukan oleh apa pun yang memakainya. Dalam paket ini pemakainya adalah gate evolusi waktu, yang dibagi menjadi satu faktor per grup, dan pass qDRIFT acak, yang menyampel seluruh grup.

Panduan ini menunjukkan cara menetapkan grup, cara memeriksa properti yang diandalkan pemakai, dan cara menata operator agar memilih beberapa grup dari yang besar tetap murah.

Catatan

Paket ini tidak menyertakan strategi pengelompokan otomatis. Kamu menetapkan indeksnya sendiri, berdasarkan apa yang kamu ketahui tentang modelmu.

Menetapkan grup​

Contoh yang dipakai adalah rantai Bose-Hubbard tiga situs. Setiap bond menyumbang pasangan hopping, dan interaksi on-site membentuk bagian diagonal. Cara paling sederhana membangun operator berkelompok adalah from_terms_with_groups(), yang menerima setiap suku bersama indeks grupnya sebagai triple (actions, coefficient, group). Kamu menentukan grup saat menuliskan suku itu, ketika kamu masih tahu mengapa ia termasuk di sana:

>>> from qiskit_bosons.operators import BosonOperator, ann, cre
>>>
>>> bonds = [(0, 1), (1, 2)]
>>> terms = []
>>> for group, (left, right) in enumerate(bonds): # one group per bond
... terms.append(([cre(left), ann(right)], -1.0, group))
... terms.append(([cre(right), ann(left)], -1.0, group))
>>> for site in range(3): # the on-site interactions share one group
... terms.append(([cre(site), cre(site), ann(site), ann(site)], 1.0, len(bonds)))
>>> hamiltonian = BosonOperator.from_terms_with_groups(terms)
>>> len(hamiltonian), hamiltonian.num_groups()
(7, 3)

Suku disimpan dalam urutan yang kamu berikan, sehingga indeks grup tidak mungkin terpasang pada suku yang salah.

Operator yang sudah ada harus dikelompokkan setelahnya, dengan menetapkan atribut groups. Di sinilah kehati-hatian diperlukan, karena from_dict() tidak menentukan urutan penyimpanan sukunya. Menuliskan daftar berdasarkan posisi bisa memasang indeks pada suku yang salah. Turunkan setiap indeks dari sukunya sendiri sebagai gantinya:

>>> existing = BosonOperator.from_dict({tuple(actions): coeff for actions, coeff, _ in terms})
>>> existing.groups = [
... len(bonds)
... if len({mode for _, mode in term}) == 1
... else bonds.index(tuple(sorted({mode for _, mode in term})))
... for term, _ in existing.iter_terms()
... ]
>>> existing.num_groups(), existing.equiv(hamiltonian)
(3, True)

Jumlah indeks harus sama dengan jumlah suku. Selain itu ditolak, karena daftar yang terlalu pendek akan diam-diam menghilangkan suku di bagian akhir di mana pun suku diiterasi bersama grupnya:

>>> try:
... hamiltonian.groups = [0, 1]
... except ValueError as error:
... print(error)
expected one group index per term, but got 2 for 7 terms

Periksa apa yang diandalkan pemakai​

Tiga fungsi di qiskit_bosons.operators.terms masing-masing menjawab satu pertanyaan sempit tentang pengelompokan yang sudah ada. Tidak satu pun menyatakan pengelompokan itu “benar”, karena kebenaran bersifat relatif terhadap pemakainya.

Apakah setiap grup Hermitian? Ini properti yang paling penting. Evolusi waktu sebuah grup hanya unitari jika grup itu Hermitian, dan satu suku hopping bi†bjb^\dagger_i b_j tidak Hermitian. Hanya pasangan bersama adjoint-nya yang Hermitian:

>>> from qiskit_bosons.operators.terms import groups_are_hermitian
>>> groups_are_hermitian(hamiltonian)
[True, True, True]

Pengelompokan yang memisahkan pasangan hopping langsung tertangkap:

>>> split = BosonOperator.from_terms_with_groups(
... [(actions, coeff, index) for index, (actions, coeff, _) in enumerate(terms)]
... ) # one term per group
>>> [bool(flag) for flag in groups_are_hermitian(split)]
[False, False, False, False, True, True, True]

Keempat suku hopping tertangkap. Tiga entri True adalah suku on-site bi†bi†bibib^\dagger_i b^\dagger_i b_i b_i, yang Hermitian dengan sendirinya. Sebuah mode boleh saja berulang di dalam satu suku, dan tidak ada yang dibuang karenanya. Flag mengikuti urutan terms, makanya tiap flag bisa dibaca bersama suku yang dijelaskannya.

Apakah koefisiennya seragam? Product formula acak memberi bobot pada sebuah grup berdasarkan rata-rata magnitudo koefisiennya, yang hanya menggambarkan grup itu dengan setia kalau magnitudonya sama:

>>> from qiskit_bosons.operators.terms import group_coeff_means, groups_have_uniform_coeffs
>>> groups_have_uniform_coeffs(hamiltonian)
[True, True, True]
>>> group_coeff_means(hamiltonian)
[1.0, 1.0, 1.0]

Kedua pengecekan ini tidak saling menyiratkan: koefisien yang seragam tidak membuat sebuah grup jadi Hermitian, dan grup Hermitian bisa saja punya magnitudo yang campur. Secara default, yang dibandingkan adalah magnitudonya, karena itulah yang dirata-ratakan oleh group_coeff_means(). Pasangan Hermitian dengan koefisien kompleks punya magnitudo yang sama tapi koefisien yang tidak sama, jadi hanya memenuhi bentuk default:

>>> conjugate = BosonOperator.from_terms_with_groups(
... [([cre(0), ann(1)], 1.0j, 0), ([cre(1), ann(0)], -1.0j, 0)]
... )
>>> groups_have_uniform_coeffs(conjugate)
[True]
>>> groups_have_uniform_coeffs(conjugate, abs=False)
[False]
Catatan

groups_are_hermitian() dibangun di atas is_hermitian(), yang membandingkan sebuah operator dengan adjoin-nya setelah normal ordering. Itu adalah identitas dari aljabar yang tidak dipotong (untruncated), jadi grup yang lolos adalah Hermitian sebagai operator bosonik. Lihat Prinsip desain representasi operator untuk cara perkalian operator ladder diurutkan dan dibandingkan.

Urutkan suku berdasarkan grup​

split_out_groups() mengembalikan satu operator untuk tiap grup yang diminta. Kalau suku-suku sebuah grup tersebar di seluruh operator, fungsi ini harus memindai setiap suku untuk menemukannya. Kalau tiap grup membentuk satu rentang yang berurutan, fungsi ini melakukan pencarian biner pada batas-batas grup, jadi biaya satu pencarian mengikuti jumlah grup yang diminta, bukan jumlah suku yang disimpan.

group_order() menghasilkan tata letak itu. Fungsi ini melakukan pengurutan stabil berdasarkan indeks grup: nilai operator tidak berubah, dan suku-suku dalam satu grup tetap mempertahankan urutan relatifnya.

>>> from qiskit_bosons.operators.terms import group_order
>>> scattered = BosonOperator.from_terms_with_groups(
... [(actions, coeff, group) for (actions, coeff, _), group in zip(terms, [1, 0, 1, 0, 2, 2, 2])]
... )
>>> ordered = group_order(scattered)
>>> ordered.groups
[0, 0, 1, 1, 2, 2, 2]
>>> ordered.equiv(scattered)
True

Kedua tata letak mengembalikan operator yang sama; hanya biayanya yang berbeda:

>>> request = [2, 0]
>>> all(
... a.equiv(b)
... for a, b in zip(
... scattered.split_out_groups(request), ordered.split_out_groups(request), strict=True
... )
... )
True

Langkah selanjutnya​

Pengelompokan dipilih di sini, di level bosonik, selagi struktur modelnya masih terlihat.