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?

Bekerja dengan circuit bosonik

Sebuah BosonicCircuit mengekspresikan komputasi langsung pada mode bosonik. Ia tidak membawa truncation, encoding, ataupun jumlah qubit: semua itu masuk belakangan, saat transpilation, sehingga satu circuit bisa diturunkan di bawah beberapa encoding dan beberapa truncation tanpa dibangun ulang.

Ia sengaja menyediakan API yang lebih ringkas dibandingkan QuantumCircuit milik Qiskit, sehingga gate qubit tidak bisa diterapkan pada mode bosonik, yang bukan operasi yang terdefinisi dengan baik. Panduan ini membahas operasi yang memang tersedia untuk merakit circuit yang lebih besar dari yang lebih kecil.

Mengapa memakai circuit bosonik​

Pertimbangkan alur kerja tradisional untuk menaruh evolusi waktu dari Hamiltonian bosonik ke arsitektur berbasis qubit:

  1. Definisikan Hamiltonian bosonik, misalnya H=−∑ijbi†bjH = -\sum_{ij} b^\dagger_i b_j.

  2. Pilih truncation dan encoding, lalu petakan Hamiltonian ke operator qubit dengan keduanya.

  3. Implementasikan evolusi waktu di ruang qubit, dengan Trotterization atau metode lain.

Langkah kedua datang di awal, dan ia membuat dua keputusan yang mahal untuk ditarik kembali. Truncation menentukan berapa level yang dipertahankan tiap mode, dan encoding menentukan berapa qubit yang dibutuhkan, sehingga keduanya terkunci dalam operator qubit sebelum hal lain dilakukan pada circuit. Untuk melihat fisika yang sama dengan cutoff atau encoding lain, kamu harus memetakan Hamiltonian lagi dan membangun circuit lagi. Selain itu, yang dibuang oleh mapping adalah struktur bosonik: suku mana yang saling terkait, dan bahwa suku-suku pasangan hopping adalah adjoint satu sama lain.

Sebuah BosonicCircuit memindahkan keputusan-keputusan itu ke akhir:

  1. Definisikan Hamiltonian bosonik.

  2. Ekspresikan evolusi waktu langsung pada mode bosonik, dengan gate bosonik.

  3. Pilih truncation dan encoding sebagai bagian dari transpilation.

Circuit menjelaskan apa komputasi yang dilakukan, dan transpilation memutuskan bagaimana menaruhnya pada qubit. Circuit yang sama lalu diturunkan pada setiap cutoff dan di bawah setiap encoding, dan pengelompokan operator masih ada untuk pass yang bisa memakainya. Bagian-bagian berikut menunjukkan cara merakit circuit semacam itu; Transpile circuit bosonik menunjukkan proses penurunannya.

Pengindeksan mode generik​

Modul operators dan circuit berbagi satu konvensi untuk mode. Mode hanyalah indeks yang melabeli satu derajat kebebasan bosonik, dan ia tidak membawa makna sendiri. Karena itu kamu bisa mengevolusikan operator apa pun yang mengimplementasikan protokol OperatorTrait, apa pun yang diwakilinya, dan circuit tidak perlu tahu apa arti mode 2. Hal yang sama berlaku untuk ukuran sebuah mode: circuit tidak punya cutoff okupasi, jadi tidak ada yang menyatakan berapa level yang dimiliki sebuah mode.

Menambahkan gate​

Gate ditambahkan ke mode. Hanya instance BosonicGate yang diterima:

>>> from qiskit_bosons.circuit import BosonicCircuit
>>> from qiskit_bosons.circuit.library import Evolution, InitializeModes
>>> from qiskit_bosons.operators import BosonOperator, ann, cre
>>>
>>> hopping = BosonOperator.from_dict({(cre(0), ann(1)): -1.0, (cre(1), ann(0)): -1.0})
>>> hopping.groups = [0] * len(hopping) # the pair is Hermitian, its terms alone are not
>>>
>>> prepare = BosonicCircuit(2)
>>> prepare.append(InitializeModes([2, 0]), prepare.modes)
>>> step = BosonicCircuit(2)
>>> step.append(Evolution(2, hopping, time=0.1), step.modes)

Yang lain ditolak, dan error-nya menyebut tipe yang bermasalah:

>>> from qiskit.circuit.library import HGate
>>> try:
... prepare.append(HGate(), [0])
... except ValueError as error:
... print(error)
Unsupported instruction type: <class '...HGate'>

Menyusun circuit​

compose() menaruh instruksi dari satu circuit ke circuit lain. Instruksi itu di-inline, bukan dibungkus menjadi satu gate, sehingga hasilnya adalah circuit biasa yang bisa terus kamu dekomposisi dan transpile.

>>> program = prepare.compose(step)
>>> program.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A composed BosonicCircuit.

Secara default circuit baru dikembalikan dan kedua operand dibiarkan. Berikan inplace=True untuk memodifikasi yang pertama, dan front=True untuk menaruh operand sebelum instruksi yang sudah ada:

>>> step.compose(prepare, front=True)._inner.data == program._inner.data
True

Circuit yang lebih sempit bisa ditaruh pada subset mode yang dipilih:

>>> single = BosonicCircuit(1)
>>> single.append(Evolution(1, BosonOperator.from_dict({(cre(0), ann(0)): 1.0}), 0.1), single.modes)
>>> wide = BosonicCircuit(3).compose(single, [2])
>>> wide.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A narrow-composed BosonicCircuit.

Hanya BosonicCircuit lain yang diterima sebagai operand, karena compose bawaan Qiskit akan meng-inline gate qubit dan melewati pemeriksaan yang diberlakukan append.

Mengulang circuit​

repeat() mengulang circuit dari ujung ke ujung. Repetisinya diratakan: hasilnya memuat instruksi sebanyak reps kali berurutan, bukan satu gate yang membungkus circuit. Karena itu, jumlah operasi berskala dengan reps, dan decompose bekerja pada badan yang diulang alih-alih menghapus satu repetisi.

>>> len(step.repeat(0)._inner.data) # zero repetitions is the identity
0
>>> step.repeat(5).draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A repeated BosonicCircuit.

Ini cara Trotterize di level circuit: evolusikan selama waktu singkat, lalu ulangi. Lihat Mensintesis Evolution gate di ruang bosonik untuk alternatif memilih product formula pada gate itu sendiri, dan mengapa keduanya adalah hal berbeda yang kebetulan memakai kata “repetisi”.

Pisahkan langkah dengan barrier​

Barrier menandai titik sinkronisasi yang tidak dilintasi pass optimisasi saat menggabungkan gate. barrier() menaruhnya pada semua mode, atau pada mode yang kamu sebutkan:

>>> program = BosonicCircuit(2)
>>> program.append(InitializeModes([2, 0]), program.modes)
>>> program.barrier()
>>> program.barrier(program.modes[0], label="zero")
>>> program.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A BosonicCircuit with barriers.

repeat(..., insert_barriers=True) menaruh satu di antara repetisi yang berurutan, dan tidak ada setelah yang terakhir:

>>> step.repeat(3, insert_barriers=True).draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A repeated BosonicCircuit with barriers.

Barrier dan encoding​

Encoding butuh beberapa qubit per mode, sehingga register mode dan register qubit berbeda ukuran, dan layout menghubungkan register utuh. Karena itu sebuah mode tidak punya qubit sendiri untuk mempersempit barrier. Selama sintesis boson-ke-qubit, barrier dipetakan ke setiap qubit dari tiap register yang disentuhnya, yang benar di bawah layout apa pun:

>>> from qiskit_bosons.mappers import LevelSpec
>>> from qiskit_bosons.transpiler.presets import generate_preset_occupation_pass_manager
>>> lowered = generate_preset_occupation_pass_manager(LevelSpec(2, "unary_projected")).run(program)
>>> lowered.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A QuantumCircuit showing the expansion of barrier to cover the entire qubit register.

Membaca hasil circuit bosonik​

Sebuah BosonicCircuit tidak punya measure atau measure_all. Arti bit yang terukur bergantung pada encoding. Di bawah encoding unary, okupasi sebuah mode tersebar di beberapa qubit dan harus dibaca dari pola bit, sedangkan di bawah encoding kompak ia berupa bilangan biner, jadi pengukuran yang menyebut sebuah mode harus tahu encodingnya, yang sengaja tidak diketahui circuit bosonik. Ukur QuantumCircuit hasil transpile sebagai gantinya, dan dekode bitstring dengan LevelEncoding.level_to_bits() dan offset dari LevelSpec yang kamu pakai untuk lowering. Simulasi dinamika Bose-Hubbard dengan pilihan encoding melakukan ini untuk model yang lengkap.

>>> hasattr(BosonicCircuit, "measure_all")
False

Langkah berikutnya​