Langkau ke kandungan utama
Projek ini dalam fasa beta. Jumpa pepijat? Buat isu GitHub. Ada soalan atau idea? Tanya dalam Discussions — kami suka dengar maklum balas anda!
Bagaimana kualiti terjemahan pada halaman ini?

Bekerja dengan litar fermionik

Important

Konsep dalam panduan ini pada masa ini hanya tersedia dalam Python API. Fungsi yang setara akan disediakan dalam C API pada keluaran akan datang.

Panduan ini menerangkan cara menggunakan FermionicCircuit untuk melaksanakan algoritma kuantum terus dalam ruang fermionik, dan bukannya memetakan kepada qubit terlebih dahulu.

Mengapa menggunakan litar fermionik​

Pertimbangkan aliran kerja tradisional untuk melaksanakan evolusi masa bagi Hamiltonian fermionik pada seni bina berasaskan qubit:

  1. Takrifkan Hamiltonian fermionik (contohnya, H=∑pqhpqcp†cqH = \sum_{pq} h_{pq} c^\dagger_p c_q).

  2. Petakannya kepada operator qubit (contohnya, dengan menggunakan pemetaan Jordan-Wigner).

  3. Laksanakan evolusi masa dalam ruang qubit (menggunakan Trotterization atau kaedah lain).

Pendekatan ini mempunyai had asas; pemetaan awal kepada qubit membuang pengetahuan yang peka masalah tentang struktur fermionik. Laluan pengoptimuman piawai tidak dapat mengeksploitasi simetri fermionik atau penyusunan semula sebutan yang dibenarkan, lalu menghasilkan litar yang tidak optimum dengan kedalaman dan bilangan Gate yang tidak perlu.

FermionicCircuit membolehkan aliran kerja yang lebih baik:

  1. Takrifkan Hamiltonian fermionik (contohnya, H=∑pqhpqcp†cqH = \sum_{pq} h_{pq} c^\dagger_p c_q).

  2. Laksanakan evolusi masa terus dalam ruang fermionik menggunakan Gate fermionik.

  3. Petakan kepada ruang qubit sebagai sebahagian daripada proses transpilasi.

Pendekatan ini menangani had tersebut dengan mengekalkan pengetahuan yang peka masalah dalam ruang fermionik, di mana laluan pengoptimuman dapat mengeksploitasi struktur fermionik dan hubungan kekomutan untuk mengurangkan kedalaman litar. Litar fermionik menerangkan pengiraan apa yang perlu dilakukan, manakala transpilasi mengendalikan cara memetakannya kepada qubit, sekali gus memberikan pengasingan tanggungjawab yang lebih kemas.

Pengindeksan mod generik​

Kedua-dua modul operators dan FermionicCircuit menggunakan pengindeksan berasaskan mod generik yang tidak membuat andaian tentang sifat mod tersebut. Mod hanyalah indeks abstrak yang melabelkan satu darjah kebebasan fermionik, tanpa semantik yang wujud. Pilihan reka bentuk ini mencerminkan modul operators dan memastikan fleksibiliti maksimum. Sebagai contoh, anda boleh melaksanakan evolusi masa bagi sebarang operator yang melaksanakan protokol OperatorTrait, tanpa mengira perwakilan matematiknya.

Bina litar fermionik​

Contoh di bawah melaksanakan evolusi masa yang diterangkan dalam bahagian sebelumnya. Ia membina FermionicCircuit dengan menentukan bilangan mod fermionik, kemudian menambah Gate fermionik daripada qiskit_fermions.circuit.library untuk melaksanakan evolusi masa.

Contoh ini juga menunjukkan cara menerapkan pengetahuan domain ke dalam operator dengan menggunakan pengumpulan sebutan operator. Dengan menetapkan indeks kumpulan kepada sebutan Hamiltonian, anda mengekalkan maklumat struktur yang dapat dieksploitasi oleh laluan pengoptimuman sepanjang tindanan transpilasi.

>>> from qiskit_fermions.circuit import FermionicCircuit
>>> from qiskit_fermions.circuit.library import Evolution
>>> from qiskit_fermions.operators import FermionOperator, cre, ann
>>>
>>> # Create a circuit with 4 fermionic modes
>>> circuit = FermionicCircuit(4)
>>>
>>> # Define a simple fermionic Hamiltonian
>>> hamiltonian = FermionOperator.from_terms([
... ([cre(0), ann(2)], 0.5),
... ([cre(2), ann(0)], 0.5),
... ([cre(1), ann(3)], 0.5),
... ([cre(3), ann(1)], 0.5),
... ])
>>> # Add some problem structure by grouping our Hamiltonian terms
>>> hamiltonian.groups = [0, 0, 1, 1]
>>>
>>> # Add an evolution gate to implement exp(-i * t * H)
>>> evolution = Evolution(4, hamiltonian, time=1.0)
>>> circuit.append(evolution, circuit.register)

A simple `FermionicCircuit` with a single time evolution gate.

A decomposed `FermionicCircuit` with several time evolution gates.

Perhatikan bagaimana pengumpulan sebutan operator dikekalkan walaupun dalam operasi mudah seperti penguraian. Ini menunjukkan bagaimana maklumat struktur mengalir melalui tindanan litar. Untuk memahami transpilasi penuh kepada qubit, rujuk panduan Transpilasi litar fermionik.

Pisahkan Gate dengan penghalang​

Laluan pengoptimuman menggabungkan Gate yang berjiran jika boleh. Sebagai contoh, MergeOrbitalRotations menggabungkan satu jujukan Gate OrbitalRotation berturutan menjadi satu, dan MergeSlaterDeterminantPreparation melipat InitializeModes ke dalam putaran yang mengikutinya.

Gunakan FermionicCircuit.barrier() apabila anda ingin menghalangnya. Penghalang tidak membawa kesan unitari, jadi ia tidak mengubah keadaan yang disediakan oleh litar anda; ia hanya menandakan satu titik yang tidak dilintasi penggabungan oleh laluan tersebut. Panggil tanpa argumen untuk merangkumi setiap mod, atau luluskan mod untuk mengehadkannya kepada:

>>> from qiskit_fermions.circuit.library import OrbitalRotation
>>> import numpy as np
>>>
>>> rotations = FermionicCircuit(4)
>>> rotations.append(OrbitalRotation(np.eye(4, dtype=complex)), rotations.register)
>>> rotations.barrier()
>>> rotations.append(OrbitalRotation(np.eye(4, dtype=complex)), rotations.register)

A `FermionicCircuit` with a barrier separating two orbital rotations.

Penghalang kekal semasa transpilasi fermion-ke-qubit, jadi ia turut mengekang pengoptimuman peringkat qubit yang menyusul. Panduan Transpilasi litar fermionik membincangkan peringkat tersebut.

Ulang litar​

Banyak algoritma menggunakan blok Gate yang sama berkali-kali. Evolusi masa ialah kes biasa: satu langkah Trotter dibina sekali, kemudian diulang untuk mencapai masa sasaran. Gunakan repeat() untuk membina litar yang diulang, dan compose() untuk menyambungkannya kepada awalan penyediaan keadaan.

Contoh di bawah membina langkah Trotter peringkat kedua untuk model Fermi-Hubbard. Langkah ini simetri: ia memecahkan sebutan lompatan kepada dua Gate OrbitalRotation berdurasi separuh yang mengapit interaksi tapak.

>>> import scipy.linalg
>>> from qiskit_fermions.circuit.library import InitializeModes, OrbitalRotation
>>>
>>> norb, reps, time = 2, 3, 1.0
>>> num_modes = 2 * norb
>>> dt = time / reps
>>>
>>> hopping = np.zeros((norb, norb))
>>> hopping[0, 1] = hopping[1, 0] = -1.0
>>> interaction = FermionOperator.from_dict(
... {(cre(p), ann(p), cre(p + norb), ann(p + norb)): 2.0 for p in range(norb)}
... )
>>>
>>> def rotation(duration):
... propagator = scipy.linalg.expm(-1j * duration * hopping)
... # the same rotation acts on the alpha and beta halves of the register
... return scipy.linalg.block_diag(propagator, propagator)
>>>
>>> trotter_step = FermionicCircuit(num_modes)
>>> trotter_step.append(OrbitalRotation(rotation(dt / 2)), trotter_step.modes)
>>> trotter_step.append(
... Evolution(num_modes, interaction, dt, atomic=True), trotter_step.modes
... )
>>> trotter_step.append(OrbitalRotation(rotation(dt / 2)), trotter_step.modes)

Mengulang langkah tersebut dan menggubahnya pada rujukan Hartree-Fock memberikan evolusi penuh:

>>> evolution = FermionicCircuit(num_modes)
>>> evolution.append(InitializeModes([True, False, True, False]), evolution.modes)
>>> evolution.compose(trotter_step.repeat(reps), inplace=True)
>>> evolution.count_ops()["OrbitalRotation"]
6

A `FermionicCircuit` with repeated steps.

Ulangan diratakan ke dalam litar yang dikembalikan dan bukannya dibungkus dalam satu Gate, jadi count_ops() mengira dua putaran bagi setiap langkah. Perataan itulah yang menjadikan lebihan pada sempadan langkah kelihatan kepada Transpiler: putaran berdurasi separuh di hujung satu langkah dan yang di permulaan langkah seterusnya bersebelahan, jadi MergeOrbitalRotations menggabungkannya menjadi satu putaran.

>>> from qiskit_fermions.transpiler import FermionicPassManager
>>> from qiskit_fermions.transpiler.passes import MergeOrbitalRotations
>>>
>>> merged = FermionicPassManager([MergeOrbitalRotations()]).run(evolution)
>>> merged.count_ops()["OrbitalRotation"]
4

A `FermionicCircuit` with repeated steps and merged orbital rotations.

Hasilnya berkos satu putaran bagi setiap langkah ditambah satu, iaitu apa yang anda peroleh dengan menggabungkan separuh langkah tersebut secara manual. Menulis langkah dalam bentuk simetri semula jadinya dan mengulanginya menghasilkan litar yang sama, jadi penggabungan diserahkan kepada peringkat pengoptimuman.

Apabila anda memerlukan ulangan diasingkan, luluskan insert_barriers=True untuk meletakkan barrier() di antaranya. Laluan pengoptimuman tidak menggabungkan Gate merentasi penghalang, jadi setiap putaran kekal:

>>> separated = trotter_step.repeat(reps, insert_barriers=True)
>>> FermionicPassManager([MergeOrbitalRotations()]).run(separated).count_ops()[
... "OrbitalRotation"
... ]
6

A `FermionicCircuit` with repeated steps separated by barriers.

Note

Argumen reps bagi FermionicSuzukiTrotter ialah konsep yang berbeza. Ia membahagikan satu Gate Evolution kepada lebih banyak faktor yang lebih pendek, manakala repeat() menggandakan litar keseluruhan. Mengulang litar yang mengandungi satu Evolution hanya mendarabkan jumlah masa evolusinya.

Ukur mod fermionik​

measure_all() membaca setiap mod ke dalam bit klasik tersendiri, memasangkan mod i dengan bit i. Gunakan measure() dengan ClassicalRegister anda sendiri untuk membaca hanya sebahagian daripadanya.

>>> measured = trotter_step.measure_all(inplace=False)
>>> measured.count_ops()["measure"]
4

Melulus inplace=False mengembalikan salinan yang diukur dan membiarkan yang asal, yang penting kerana pengukuran tidak unitari: litar yang membawanya tidak lagi boleh dikenakan pada vektor keadaan, jadi simpan litar yang tidak diukur jika anda juga ingin mensimulasikannya.

Mengukur di sini, dan bukannya pada QuantumCircuit yang telah ditranspil, menjadikan rentetan bit yang disampel mudah dibaca. Pengukuran fermionik menamakan mod yang dibacanya, jadi setiap peringkat yang mengalihkan mod (RelabelModes pada peringkat fermionik, susun atur dan penghalaan pada peringkat qubit) membawa pengukuran bersamanya, dan rentetan bit kekal diindeks mengikut mod yang anda tanyakan.

Note

Tidak seperti measure_all(), tiada barrier() disisipkan sebelum pengukuran. Panggil barrier() sendiri terlebih dahulu jika anda mahukannya di situ.

Sama ada bit yang diukur bermaksud seperti yang anda jangkakan bergantung pada pengekodan fermion-ke-qubit, yang dipilih semasa transpilasi dan bukan di sini. Di bawah pengekodan berasaskan asas penghunian seperti Jordan-Wigner, setiap mod dibawa oleh satu qubit dan bit tersebut ialah penghunian mod itu; lihat FermionicMeasure.

Transpilasi litar fermionik​

Untuk melaksanakan algoritma kuantum yang diwakili oleh FermionicCircuit anda, ia mesti ditranspil kepada QuantumCircuit. Anda boleh mempelajari cara melakukannya dalam panduan Transpilasi litar fermionik.

Langkah seterusnya​