Langkau ke kandungan utama

Fungsi kos

Dalam pelajaran ini, kita akan belajar cara menilai sebuah fungsi kos:

  • Pertama, kita akan belajar tentang primitif Qiskit Runtime
  • Tentukan sebuah fungsi kos C(θ)C(\vec\theta). Ini adalah fungsi khusus masalah yang mentakrifkan matlamat masalah untuk pengoptimum meminimumkan (atau memaksimumkan)
  • Menentukan strategi pengukuran dengan primitif Qiskit Runtime untuk mengoptimumkan kelajuan berbanding ketepatan

 

Rajah yang menunjukkan komponen utama fungsi kos termasuk penggunaan primitif seperti estimator dan sampler.

Primitif

Semua sistem fizikal, sama ada klasik atau kuantum, boleh wujud dalam pelbagai keadaan. Sebagai contoh, sebuah kereta di jalan raya boleh mempunyai jisim, kedudukan, kelajuan, atau pecutan tertentu yang mencirikan keadaannya. Begitu juga, sistem kuantum juga boleh mempunyai pelbagai konfigurasi atau keadaan, tetapi ia berbeza daripada sistem klasik dari segi cara kita mengendalikan pengukuran dan evolusi keadaan. Ini membawa kepada sifat unik seperti superposisi dan keterikatan yang eksklusif kepada mekanik kuantum. Sama seperti kita boleh menerangkan keadaan kereta menggunakan sifat fizikal seperti kelajuan atau pecutan, kita juga boleh menerangkan keadaan sistem kuantum menggunakan boleh cerapan (observables), yang merupakan objek matematik.

Dalam mekanik kuantum, keadaan diwakili oleh vektor lajur kompleks yang ternormal, atau ket (ψ|\psi\rangle), dan boleh cerapan adalah pengoperasi linear Hermitian (H^=H^\hat{H}=\hat{H}^{\dagger}) yang bertindak ke atas ket. Vektor eigen (λ|\lambda\rangle) bagi sesuatu boleh cerapan dikenali sebagai eigenstate. Mengukur sesuatu boleh cerapan untuk salah satu eigenstatenya (λ|\lambda\rangle) akan menghasilkan nilai eigen (λ\lambda) yang sepadan sebagai bacaan.

Jika kamu tertanya-tanya cara mengukur sistem kuantum dan apa yang boleh diukur, Qiskit menawarkan dua primitif yang boleh membantu:

  • Sampler: Diberi keadaan kuantum ψ|\psi\rangle, primitif ini mendapatkan kebarangkalian setiap keadaan asas pengiraan yang mungkin.
  • Estimator: Diberi boleh cerapan kuantum H^\hat{H} dan keadaan ψ|\psi\rangle, primitif ini mengira nilai jangkaan H^\hat{H}.

Primitif Sampler

Primitif Sampler mengira kebarangkalian mendapatkan setiap keadaan yang mungkin k|k\rangle daripada asas pengiraan, diberi litar kuantum yang menyediakan keadaan ψ|\psi\rangle. Ia mengira

pk=kψ2kZ2n{0,1,,2n1},p_k = |\langle k | \psi \rangle|^2 \quad \forall k \in \mathbb{Z}_2^n \equiv \{0,1,\cdots,2^n-1\},

Di mana nn adalah bilangan qubit, dan kk ialah perwakilan integer bagi mana-mana rentetan binari output yang mungkin {0,1}n\{0,1\}^n (iaitu, integer asas 22).

Sampler Qiskit Runtime menjalankan litar beberapa kali pada peranti kuantum, melakukan pengukuran pada setiap jalankan, dan membina semula taburan kebarangkalian daripada rentetan bit yang diperoleh. Lebih banyak jalankan (atau shots) yang dilakukan, semakin tepat hasilnya, tetapi ini memerlukan lebih banyak masa dan sumber kuantum.

Walau bagaimanapun, oleh kerana bilangan output yang mungkin meningkat secara eksponen dengan bilangan qubit nn (iaitu, 2n2^n), bilangan shots juga perlu meningkat secara eksponen bagi menangkap taburan kebarangkalian yang padat. Oleh itu, Sampler hanya cekap untuk taburan kebarangkalian yang jarang; di mana keadaan sasaran ψ|\psi\rangle mestilah boleh dinyatakan sebagai gabungan linear bagi keadaan asas pengiraan, dengan bilangan sebutan yang meningkat paling banyak secara polinomial dengan bilangan qubit:

ψ=kPoly(n)wkk.|\psi\rangle = \sum^{\text{Poly}(n)}_k w_k |k\rangle.

Sampler juga boleh dikonfigurasi untuk mendapatkan kebarangkalian daripada bahagian litar, yang mewakili subset bagi semua keadaan yang mungkin.

Primitif Estimator

Primitif Estimator mengira nilai jangkaan bagi boleh cerapan H^\hat{H} untuk keadaan kuantum ψ|\psi\rangle; di mana kebarangkalian boleh cerapan boleh dinyatakan sebagai pλ=λψ2p_\lambda = |\langle\lambda|\psi\rangle|^2, dengan λ|\lambda\rangle ialah eigenstate bagi boleh cerapan H^\hat{H}. Nilai jangkaan kemudiannya ditakrifkan sebagai purata semua hasil yang mungkin λ\lambda (iaitu, nilai eigen bagi boleh cerapan) bagi pengukuran keadaan ψ|\psi\rangle, berpemberat dengan kebarangkalian yang sepadan:

H^ψ:=λpλλ=ψH^ψ\langle\hat{H}\rangle_\psi := \sum_\lambda p_\lambda \lambda = \langle \psi | \hat{H} | \psi \rangle

Walau bagaimanapun, mengira nilai jangkaan sesuatu boleh cerapan tidak selalunya boleh dilakukan, kerana kita sering tidak tahu asas eigennya. Estimator Qiskit Runtime menggunakan proses algebra yang kompleks untuk menganggar nilai jangkaan pada peranti kuantum sebenar dengan menguraikan boleh cerapan tersebut kepada gabungan boleh cerapan lain yang asas eigennya kita sudah ketahui.

Secara lebih mudah, Estimator menguraikan mana-mana boleh cerapan yang tidak tahu cara mengukurnya kepada boleh cerapan yang lebih mudah dan boleh diukur yang dipanggil pengoperasi Pauli. Mana-mana pengoperasi boleh dinyatakan sebagai gabungan 4n4^n pengoperasi Pauli.

P^k:=σkn1σk0kZ4n{0,1,,4n1},\hat{P}_k := \sigma_{k_{n-1}}\otimes \cdots \otimes \sigma_{k_0} \quad \forall k \in \mathbb{Z}_4^n \equiv \{0,1,\cdots,4^n-1\}, \\

sedemikian

H^=k=04n1wkP^k\hat{H} = \sum^{4^n-1}_{k=0} w_k \hat{P}_k

di mana nn adalah bilangan qubit, kkn1k0k \equiv k_{n-1} \cdots k_0 untuk klZ4{0,1,2,3}k_l \in \mathbb{Z}_4 \equiv \{0, 1, 2, 3\} (iaitu, integer asas 44), dan (σ0,σ1,σ2,σ3):=(I,X,Y,Z)(\sigma_0, \sigma_1, \sigma_2, \sigma_3) := (I, X, Y, Z).

Selepas melakukan penguraian ini, Estimator menghasilkan litar baru VkψV_k|\psi\rangle untuk setiap boleh cerapan P^k\hat{P}_k (daripada litar asal), untuk secara efektif mendiagonalkan boleh cerapan Pauli dalam asas pengiraan dan mengukurnya. Kita boleh mengukur boleh cerapan Pauli dengan mudah kerana kita tahu VkV_k lebih awal, yang tidak berlaku secara umum untuk boleh cerapan lain.

Untuk setiap P^k\hat{P}_{k}, Estimator menjalankan litar yang sepadan pada peranti kuantum beberapa kali, mengukur keadaan output dalam asas pengiraan, dan mengira kebarangkalian pkjp_{kj} untuk mendapatkan setiap output yang mungkin jj. Ia kemudian mencari nilai eigen λkj\lambda_{kj} bagi PkP_k yang sepadan dengan setiap output jj, darabkan dengan wkw_k, dan tambah semua hasilnya untuk mendapatkan nilai jangkaan boleh cerapan H^\hat{H} bagi keadaan ψ|\psi\rangle yang diberikan.

H^ψ=k=04n1wkj=02n1pkjλkj,\langle\hat{H}\rangle_\psi = \sum_{k=0}^{4^n-1} w_k \sum_{j=0}^{2^n-1}p_{kj} \lambda_{kj},

Oleh kerana mengira nilai jangkaan 4n4^n Pauli adalah tidak praktikal (iaitu, pertumbuhan eksponen), Estimator hanya boleh cekap apabila banyak wkw_k adalah sifar (iaitu, penguraian Pauli yang jarang berbanding padat). Secara formal kita katakan bahawa, agar pengiraan ini boleh diselesaikan dengan cekap, bilangan sebutan bukan sifar mestilah meningkat paling banyak secara polinomial dengan bilangan qubit nn: H^=kPoly(n)wkP^k.\hat{H} = \sum^{\text{Poly}(n)}_k w_k \hat{P}_k.

Pembaca mungkin perasan andaian tersirat bahawa pensampelan kebarangkalian juga perlu cekap seperti yang dijelaskan untuk Sampler, yang bermaksud

H^ψ=kPoly(n)wkjPoly(n)pkjλkj.\langle\hat{H}\rangle_\psi = \sum_{k}^{\text{Poly}(n)} w_k \sum_{j}^{\text{Poly}(n)}p_{kj} \lambda_{kj}.

Contoh berpandu untuk mengira nilai jangkaan

Mari kita andaikan keadaan satu qubit +:=H0=12(0+1)|+\rangle := H|0\rangle = \frac{1}{\sqrt{2}}(|0\rangle + |1\rangle), dan boleh cerapan

H^=(1221)=2XZ\begin{aligned} \hat{H} & = \begin{pmatrix} -1 & 2 \\ 2 & 1 \\ \end{pmatrix}\\[1mm] & = 2X - Z \end{aligned}

dengan nilai jangkaan teori berikut H^+=+H^+=2.\langle\hat{H}\rangle_+ = \langle+|\hat{H}|+\rangle = 2.

Oleh kerana kita tidak tahu cara mengukur boleh cerapan ini, kita tidak boleh mengira nilai jangkaannya secara terus, dan kita perlu menyatakannya semula sebagai H^+=2X+Z+\langle\hat{H}\rangle_+ = 2\langle X \rangle_+ - \langle Z \rangle_+ . Yang boleh ditunjukkan memberikan hasil yang sama dengan memperhatikan bahawa +X+=1\langle+|X|+\rangle = 1, dan +Z+=0\langle+|Z|+\rangle = 0.

Mari kita lihat cara mengira X+\langle X \rangle_+ dan Z+\langle Z \rangle_+ secara terus. Oleh kerana XX dan ZZ tidak bertukar (iaitu, mereka tidak berkongsi asas eigen yang sama), mereka tidak boleh diukur serentak, oleh itu kita memerlukan litar pembantu:

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime rustworkx
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp

# The following code will work for any other initial single-qubit state and observable
original_circuit = QuantumCircuit(1)
original_circuit.h(0)

H = SparsePauliOp(["X", "Z"], [2, -1])

aux_circuits = []
for pauli in H.paulis:
aux_circ = original_circuit.copy()
aux_circ.barrier()
if str(pauli) == "X":
aux_circ.h(0)
elif str(pauli) == "Y":
aux_circ.sdg(0)
aux_circ.h(0)
else:
aux_circ.id(0)
aux_circ.measure_all()
aux_circuits.append(aux_circ)

original_circuit.draw("mpl")

Output of the previous code cell

# Auxiliary circuit for X
aux_circuits[0].draw("mpl")

Output of the previous code cell

# Auxiliary circuit for Z
aux_circuits[1].draw("mpl")

Output of the previous code cell

Kita kini boleh menjalankan pengiraan secara manual menggunakan Sampler dan semak hasilnya dengan Estimator:

from qiskit.primitives import StatevectorSampler, StatevectorEstimator
from qiskit.result import QuasiDistribution
import numpy as np

## SAMPLER
shots = 10000
sampler = StatevectorSampler()
job = sampler.run(aux_circuits, shots=shots)

# Run the sampler job and step through results
expvals = []
for index, pauli in enumerate(H.paulis):
data_pub = job.result()[index].data
bitstrings = data_pub.meas.get_bitstrings()
counts = data_pub.meas.get_counts()
quasi_dist = QuasiDistribution(
{outcome: freq / shots for outcome, freq in counts.items()}
)

# Use the probabilities and known eigenvalues of Pauli operators to estimate the expectation value.
val = 0

if str(pauli) == "X":
val += -1 * quasi_dist.get(1, 0)
val += 1 * quasi_dist.get(0, 0)

if str(pauli) == "Y":
val += -1 * quasi_dist.get(1, 0)
val += 1 * quasi_dist.get(0, 0)

if str(pauli) == "Z":
val += 1 * quasi_dist.get(0, 0)
val += -1 * quasi_dist.get(1, 0)

expvals.append(val)

# Print expectation values

print("Sampler results:")
for pauli, expval in zip(H.paulis, expvals):
print(f" >> Expected value of {str(pauli)}: {expval:.5f}")

total_expval = np.sum(H.coeffs * expvals).real
print(f" >> Total expected value: {total_expval:.5f}")

# Use estimator for comparison
observables = [
*H.paulis,
H,
] # Note: run for individual Paulis as well as full observable H

estimator = StatevectorEstimator()
job = estimator.run([(original_circuit, observables)])
estimator_expvals = job.result()[0].data.evs

# Print results
print("Estimator results:")
for obs, expval in zip(observables, estimator_expvals):
if obs is not H:
print(f" >> Expected value of {str(obs)}: {expval:.5f}")
else:
print(f" >> Total expected value: {expval:.5f}")
Sampler results:
>> Expected value of X: 1.00000
>> Expected value of Z: 0.00420
>> Total expected value: 1.99580
Estimator results:
>> Expected value of X: 1.00000
>> Expected value of Z: 0.00000
>> Total expected value: 2.00000

Ketepatan matematik (pilihan)

Dengan menyatakan ψ|\psi\rangle terhadap asas eigenstate H^\hat{H}, ψ=λaλλ|\psi\rangle = \sum_\lambda a_\lambda |\lambda\rangle, diperoleh:

ψH^ψ=(λaλλ)H^(λaλλ)=λλaλaλλH^λ=λλaλaλλλλ=λλaλaλλδλ,λ=λaλ2λ=λpλλ\begin{aligned} \langle \psi | \hat{H} | \psi \rangle & = \bigg(\sum_{\lambda'}a^*_{\lambda'} \langle \lambda'|\bigg) \hat{H} \bigg(\sum_{\lambda} a_\lambda | \lambda\rangle\bigg)\\[1mm] & = \sum_{\lambda}\sum_{\lambda'} a^*_{\lambda'}a_{\lambda} \langle \lambda'|\hat{H}| \lambda\rangle\\[1mm] & = \sum_{\lambda}\sum_{\lambda'} a^*_{\lambda'}a_{\lambda} \lambda \langle \lambda'| \lambda\rangle\\[1mm] & = \sum_{\lambda}\sum_{\lambda'} a^*_{\lambda'}a_{\lambda} \lambda \cdot \delta_{\lambda, \lambda'}\\[1mm] & = \sum_\lambda |a_\lambda|^2 \lambda\\[1mm] & = \sum_\lambda p_\lambda \lambda\\[1mm] \end{aligned}

Oleh kerana kita tidak tahu nilai eigen atau eigenstate bagi boleh cerapan sasaran H^\hat{H}, pertama kita perlu mempertimbangkan penpepenjurunya. Memandangkan H^\hat{H} adalah Hermitian, terdapat transformasi unitari VV sedemikian H^=VΛV,\hat{H}=V^\dagger \Lambda V, di mana Λ\Lambda adalah matriks nilai eigen pepenjuru, jadi jΛk=0\langle j | \Lambda | k \rangle = 0 jika jkj\neq k, dan jΛj=λj\langle j | \Lambda | j \rangle = \lambda_j.

Ini bermakna nilai jangkaan boleh ditulis semula sebagai:

ψH^ψ=ψVΛVψ=ψV(j=02n1jj)Λ(k=02n1kk)Vψ=j=02n1k=02n1ψVjjΛkkVψ=j=02n1ψVjjΛjjVψ=j=02n1jVψ2λj\begin{aligned} \langle\psi|\hat{H}|\psi\rangle & = \langle\psi|V^\dagger \Lambda V|\psi\rangle\\[1mm] & = \langle\psi|V^\dagger \bigg(\sum_{j=0}^{2^n-1} |j\rangle \langle j|\bigg) \Lambda \bigg(\sum_{k=0}^{2^n-1} |k\rangle \langle k|\bigg) V|\psi\rangle\\[1mm] & = \sum_{j=0}^{2^n-1} \sum_{k=0}^{2^n-1}\langle\psi|V^\dagger |j\rangle \langle j| \Lambda |k\rangle \langle k| V|\psi\rangle\\[1mm] & = \sum_{j=0}^{2^n-1}\langle\psi|V^\dagger |j\rangle \langle j| \Lambda |j\rangle \langle j| V|\psi\rangle\\[1mm] & = \sum_{j=0}^{2^n-1}|\langle j| V|\psi\rangle|^2 \lambda_j\\[1mm] \end{aligned}

Memandangkan jika sistem berada dalam keadaan ϕ=Vψ|\phi\rangle = V |\psi\rangle kebarangkalian mengukur j| j\rangle adalah pj=jϕ2p_j = |\langle j|\phi \rangle|^2, nilai jangkaan di atas boleh dinyatakan sebagai:

ψH^ψ=j=02n1pjλj.\langle\psi|\hat{H}|\psi\rangle = \sum_{j=0}^{2^n-1} p_j \lambda_j.

Adalah sangat penting untuk diperhatikan bahawa kebarangkalian diambil daripada keadaan VψV |\psi\rangle bukannya ψ|\psi\rangle. Inilah sebabnya matriks VV adalah amat diperlukan. Mungkin kamu tertanya-tanya cara mendapatkan matriks VV dan nilai eigen Λ\Lambda. Jika kamu sudah mempunyai nilai eigen, maka tidak perlu menggunakan komputer kuantum kerana matlamat algoritma variatif adalah untuk mencari nilai eigen H^\hat{H} tersebut.

Nasib baik, ada jalan keluarnya: mana-mana matriks 2n×2n2^n \times 2^n boleh ditulis sebagai gabungan linear bagi 4n4^n hasil darab tensor bagi nn matriks Pauli dan identiti, yang semuanya adalah Hermitian dan unitari dengan VV dan Λ\Lambda yang diketahui. Inilah yang dilakukan oleh Estimator Runtime secara dalaman dengan menguraikan mana-mana objek Operator kepada SparsePauliOp.

Berikut adalah Pengoperasi yang boleh digunakan:

OperatorσVΛIσ0=(1001)V0=IΛ0=I=(1001)Xσ1=(0110)V1=H=12(1111)Λ1=σ3=(1001)Yσ2=(0ii0)V2=HS=12(1111)(100i)=12(1i1i)Λ2=σ3=(1001)Zσ3=(1001)V3=IΛ3=σ3=(1001)\begin{array}{c|c|c|c} \text{Operator} & \sigma & V & \Lambda \\[1mm] \hline I & \sigma_0 = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} & V_0 = I & \Lambda_0 = I = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} \\[4mm] X & \sigma_1 = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} & V_1 = H =\frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix} & \Lambda_1 = \sigma_3 = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} \\[4mm] Y & \sigma_2 = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix} & V_2 = HS^\dagger =\frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}\cdot \begin{pmatrix} 1 & 0 \\ 0 & -i \end{pmatrix} = \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & -i \\ 1 & i \end{pmatrix}\quad & \Lambda_2 = \sigma_3 = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} \\[4mm] Z & \sigma_3 = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} & V_3 = I & \Lambda_3 = \sigma_3 = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} \end{array}

Jadi mari kita tulis semula H^\hat{H} terhadap Pauli dan identiti:

H^=kn1=03...k0=03wkn1...k0σkn1...σk0=k=04n1wkP^k,\hat{H} = \sum_{k_{n-1}=0}^3... \sum_{k_0=0}^3 w_{k_{n-1}...k_0} \sigma_{k_{n-1}}\otimes ... \otimes \sigma_{k_0} = \sum_{k=0}^{4^n-1} w_k \hat{P}_k,

di mana k=l=0n14lklkn1...k0k = \sum_{l=0}^{n-1} 4^l k_l \equiv k_{n-1}...k_0 untuk kn1,...,k0{0,1,2,3}k_{n-1},...,k_0\in \{0,1,2,3\} (iaitu, asas 44), dan P^k:=σkn1...σk0\hat{P}_{k} := \sigma_{k_{n-1}}\otimes ... \otimes \sigma_{k_0}:

ψH^ψ=k=04n1wkj=02n1jVkψ2jΛkj=k=04n1wkj=02n1pkjλkj,\begin{aligned} \langle\psi|\hat{H}|\psi\rangle & = \sum_{k=0}^{4^n-1} w_k \sum_{j=0}^{2^n-1}|\langle j| V_k|\psi\rangle|^2 \langle j| \Lambda_k |j\rangle \\[1mm] & = \sum_{k=0}^{4^n-1} w_k \sum_{j=0}^{2^n-1}p_{kj} \lambda_{kj}, \\[1mm] \end{aligned}

di mana Vk:=Vkn1...Vk0V_k := V_{k_{n-1}}\otimes ... \otimes V_{k_0} dan Λk:=Λkn1...Λk0\Lambda_k := \Lambda_{k_{n-1}}\otimes ... \otimes \Lambda_{k_0}, sedemikian: Pk^=VkΛkVk.\hat{P_k}=V_k^\dagger \Lambda_k V_k.

Fungsi kos

Secara umum, fungsi kos digunakan untuk menggambarkan matlamat sesuatu masalah dan sejauh mana keadaan percubaan berfungsi berkenaan dengan matlamat tersebut. Definisi ini boleh digunakan dalam pelbagai contoh dalam kimia, pembelajaran mesin, kewangan, pengoptimuman, dan sebagainya.

Mari kita pertimbangkan contoh mudah untuk mencari keadaan asas sesuatu sistem. Objektif kita adalah untuk meminimumkan nilai jangkaan bagi observable yang mewakili tenaga (Hamiltonian H^\hat{\mathcal{H}}):

minθψ(θ)H^ψ(θ)\min_{\vec\theta} \langle\psi(\vec\theta)|\hat{\mathcal{H}}|\psi(\vec\theta)\rangle

Kita boleh menggunakan Estimator untuk mengira nilai jangkaan dan menghantar nilai ini kepada pengoptimum untuk diminimumkan. Jika pengoptimuman berjaya, ia akan mengembalikan set nilai parameter optimum θ\vec\theta^*, dari mana kita akan dapat membina keadaan penyelesaian yang dicadangkan ψ(θ)|\psi(\vec\theta^*)\rangle dan mengira nilai jangkaan yang diperhatikan sebagai C(θ)C(\vec\theta^*).

Perhatikan bahawa kita hanya akan dapat meminimumkan fungsi kos untuk set keadaan terhad yang sedang kita pertimbangkan. Ini membawa kepada dua kemungkinan yang berbeza:

  • Ansatz kita tidak mentakrifkan keadaan penyelesaian merentas ruang carian: Jika ini berlaku, pengoptimum kita tidak akan pernah menemui penyelesaian, dan kita perlu bereksperimen dengan ansatz lain yang mungkin dapat mewakili ruang carian kita dengan lebih tepat.
  • Pengoptimum kita tidak dapat menemui penyelesaian yang sah ini: Pengoptimuman boleh ditakrifkan secara global dan ditakrifkan secara lokal. Kita akan meneroka maksudnya dalam bahagian kemudian.

Secara keseluruhannya, kita akan melakukan gelung pengoptimuman klasik tetapi bergantung pada penilaian fungsi kos kepada komputer kuantum. Dari perspektif ini, seseorang boleh menganggap pengoptimuman sebagai usaha klasik semata-mata di mana kita memanggil beberapa oracle kuantum kotak hitam setiap kali pengoptimum perlu menilai fungsi kos.

def cost_func_vqe(params, circuit, hamiltonian, estimator):
"""Return estimate of energy from estimator

Parameters:
params (ndarray): Array of ansatz parameters
ansatz (QuantumCircuit): Parameterized ansatz circuit
hamiltonian (SparsePauliOp): Operator representation of Hamiltonian
estimator (Estimator): Estimator primitive instance

Returns:
float: Energy estimate
"""
pub = (circuit, hamiltonian, params)
cost = estimator.run([pub]).result()[0].data.evs
return cost
from qiskit.circuit.library import TwoLocal

observable = SparsePauliOp.from_list([("XX", 1), ("YY", -3)])

reference_circuit = QuantumCircuit(2)
reference_circuit.x(0)

variational_form = TwoLocal(
2,
rotation_blocks=["rz", "ry"],
entanglement_blocks="cx",
entanglement="linear",
reps=1,
)
ansatz = reference_circuit.compose(variational_form)

theta_list = (2 * np.pi * np.random.rand(1, 8)).tolist()
ansatz.decompose().draw("mpl")

Output of the previous code cell

Kita akan melakukan ini terlebih dahulu menggunakan simulator: StatevectorEstimator. Ini biasanya disyorkan untuk penyahpepijatan, tetapi kita akan segera mengikuti larian penyahpepijatan dengan pengiraan pada perkakasan kuantum sebenar. Semakin banyak masalah yang menarik kini tidak lagi boleh disimulasikan secara klasik tanpa kemudahan superkomputer terkini.

estimator = StatevectorEstimator()
cost = cost_func_vqe(theta_list, ansatz, observable, estimator)
print(cost)
[-0.58744589]

Kita akan meneruskan dengan menjalankan pada komputer kuantum sebenar. Perhatikan perubahan sintaks. Langkah-langkah yang melibatkan pass_manager akan dibincangkan lebih lanjut dalam contoh seterusnya. Satu langkah yang amat penting dalam algoritma variasi ialah penggunaan sesi Qiskit Runtime. Memulakan sesi membolehkan anda menjalankan berbilang iterasi algoritma variasi tanpa menunggu dalam giliran baru setiap kali parameter dikemas kini. Ini penting jika masa giliran panjang dan/atau banyak iterasi diperlukan. Hanya rakan kongsi dalam Rangkaian IBM Quantum® boleh menggunakan sesi Runtime. Jika anda tidak mempunyai akses kepada sesi, anda boleh mengurangkan bilangan iterasi yang anda hantar pada satu masa, dan simpan parameter terkini untuk digunakan dalam larian masa depan. Jika anda menghantar terlalu banyak iterasi atau menghadapi masa giliran yang terlalu panjang, anda mungkin akan menemui kod ralat 1217, yang merujuk kepada kelewatan panjang antara penghantaran kerja.

# Estimated usage: < 1 min. Benchmarked at 7 seconds on an Eagle processor
# Load necessary packages:

from qiskit_ibm_runtime import (
QiskitRuntimeService,
Session,
EstimatorOptions,
EstimatorV2 as Estimator,
)
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

# Select the least busy backend:

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, min_num_qubits=ansatz.num_qubits, simulator=False
)
# Or get a specific backend:
# backend = service.backend("ibm_brisbane")

# Use a pass manager to transpile the circuit and observable for the specific backend being used:

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_ansatz = pm.run(ansatz)
isa_observable = observable.apply_layout(layout=isa_ansatz.layout)

# Set estimator options
estimator_options = EstimatorOptions(resilience_level=1, default_shots=10_000)

# Open a Runtime session:

with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)
cost = cost_func_vqe(theta_list, isa_ansatz, isa_observable, estimator)

session.close()
print(cost)

Perhatikan bahawa nilai yang diperoleh daripada dua pengiraan di atas adalah sangat serupa. Teknik untuk memperbaiki keputusan akan dibincangkan lebih lanjut di bawah.

Contoh pemetaan kepada sistem bukan fizikal

Masalah potongan maksimum (Max-Cut) ialah masalah pengoptimuman kombinatorial yang melibatkan pembahagian bucu graf kepada dua set yang tidak bertindih sedemikian rupa sehingga bilangan tepi antara dua set dimaksimumkan. Lebih formal, diberikan graf tak berarah G=(V,E)G=(V,E), di mana VV ialah set bucu dan EE ialah set tepi, masalah Max-Cut meminta pembahagian bucu kepada dua subset yang tidak bertindih, SS dan TT, sedemikian rupa sehingga bilangan tepi dengan satu titik hujung dalam SS dan yang lain dalam TT dimaksimumkan.

Kita boleh menggunakan Max-Cut untuk menyelesaikan pelbagai masalah termasuk: pengkelompokan, reka bentuk rangkaian, peralihan fasa, dan sebagainya. Kita akan mulakan dengan membina graf masalah:

import rustworkx as rx
from rustworkx.visualization import mpl_draw

n = 4
G = rx.PyGraph()
G.add_nodes_from(range(n))
# The edge syntax is (start, end, weight)
edges = [(0, 1, 1.0), (0, 2, 1.0), (0, 3, 1.0), (1, 2, 1.0), (2, 3, 1.0)]
G.add_edges_from(edges)

mpl_draw(
G, pos=rx.shell_layout(G), with_labels=True, edge_labels=str, node_color="#1192E8"
)

Output of the previous code cell

Masalah ini boleh dinyatakan sebagai masalah pengoptimuman binari. Untuk setiap nod 0i<n0 \leq i < n, di mana nn ialah bilangan nod graf (dalam kes ini n=4n=4), kita akan mempertimbangkan pemboleh ubah binari xix_i. Pemboleh ubah ini akan bernilai 11 jika nod ii berada dalam salah satu kumpulan yang kita labelkan 11 dan 00 jika berada dalam kumpulan lain yang kita labelkan sebagai 00. Kita juga akan menandakan sebagai wijw_{ij} (elemen (i,j)(i,j) bagi matriks jiran ww) berat tepi yang menghubungkan nod ii ke nod jj. Kerana graf tidak berarah, wij=wjiw_{ij}=w_{ji}. Kemudian kita boleh merumuskan masalah kita sebagai memaksimumkan fungsi kos berikut:

C(x)=i,j=0nwijxi(1xj)=i,j=0nwijxii,j=0nwijxixj=i,j=0nwijxii=0nj=0i2wijxixj\begin{aligned} C(\vec{x}) & =\sum_{i,j=0}^n w_{ij} x_i(1-x_j)\\[1mm] & = \sum_{i,j=0}^n w_{ij} x_i - \sum_{i,j=0}^n w_{ij} x_ix_j\\[1mm] & = \sum_{i,j=0}^n w_{ij} x_i - \sum_{i=0}^n \sum_{j=0}^i 2w_{ij} x_ix_j \end{aligned}

Untuk menyelesaikan masalah ini dengan komputer kuantum, kita akan menyatakan fungsi kos sebagai nilai jangkaan observable. Walau bagaimanapun, observable yang Qiskit terima secara asli terdiri daripada operator Pauli, yang mempunyai nilai eigen 11 dan 1-1 bukannya 00 dan 11. Itulah sebabnya kita akan membuat penggantian pemboleh ubah berikut:

Di mana x=(x0,x1,,xn1)\vec{x}=(x_0,x_1,\cdots ,x_{n-1}). Kita boleh menggunakan matriks jiran ww untuk mengakses berat semua tepi dengan mudah. Ini akan digunakan untuk mendapatkan fungsi kos kita:

zi=12xixi=1zi2z_i = 1-2x_i \rightarrow x_i = \frac{1-z_i}{2}

Ini bermakna:

xi=0zi=1xi=1zi=1.\begin{array}{lcl} x_i=0 & \rightarrow & z_i=1 \\ x_i=1 & \rightarrow & z_i=-1.\end{array}

Jadi fungsi kos baru yang ingin kita maksimumkan ialah:

C(z)=i,j=0nwij(1zi2)(11zj2)=i,j=0nwij4i,j=0nwij4zizj=i=0nj=0iwij2i=0nj=0iwij2zizj\begin{aligned} C(\vec{z}) & = \sum_{i,j=0}^n w_{ij} \bigg(\frac{1-z_i}{2}\bigg)\bigg(1-\frac{1-z_j}{2}\bigg)\\[1mm] & = \sum_{i,j=0}^n \frac{w_{ij}}{4} - \sum_{i,j=0}^n \frac{w_{ij}}{4} z_iz_j\\[1mm] & = \sum_{i=0}^n \sum_{j=0}^i \frac{w_{ij}}{2} - \sum_{i=0}^n \sum_{j=0}^i \frac{w_{ij}}{2} z_iz_j \end{aligned}

Selain itu, kecenderungan semula jadi komputer kuantum adalah untuk mencari minima (biasanya tenaga terendah) bukannya maksima, jadi daripada memaksimumkan C(z)C(\vec{z}) kita akan meminimumkan:

C(z)=i=0nj=0iwij2zizji=0nj=0iwij2-C(\vec{z}) = \sum_{i=0}^n \sum_{j=0}^i \frac{w_{ij}}{2} z_iz_j - \sum_{i=0}^n \sum_{j=0}^i \frac{w_{ij}}{2}

Kini kita mempunyai fungsi kos untuk diminimumkan yang pemboleh ubahnya boleh bernilai 1-1 dan 11, kita boleh membuat analogi berikut dengan Pauli ZZ:

ziZi=In1...Zi...I0z_i \equiv Z_i = \overbrace{I}^{n-1}\otimes ... \otimes \overbrace{Z}^{i} \otimes ... \otimes \overbrace{I}^{0}

Dengan kata lain, pemboleh ubah ziz_i akan setara dengan Gate ZZ yang bertindak pada Qubit ii. Tambahan pula:

Zixn1x0=zixn1x0xn1x0Zixn1x0=ziZ_i|x_{n-1}\cdots x_0\rangle = z_i|x_{n-1}\cdots x_0\rangle \rightarrow \langle x_{n-1}\cdots x_0 |Z_i|x_{n-1}\cdots x_0\rangle = z_i

Kemudian observable yang kita akan pertimbangkan ialah:

H^=i=0nj=0iwij2ZiZj\hat{H} = \sum_{i=0}^n \sum_{j=0}^i \frac{w_{ij}}{2} Z_iZ_j

di mana kita perlu menambah sebutan bebas selepas itu:

offset=i=0nj=0iwij2\texttt{offset} = - \sum_{i=0}^n \sum_{j=0}^i \frac{w_{ij}}{2}

Operator ini ialah gabungan linear bagi sebutan dengan operator Z pada nod yang dihubungkan oleh tepi (ingat bahawa Qubit ke-0 berada paling kanan): IIZZ+IZIZ+IZZI+ZIIZ+ZZIIIIZZ + IZIZ + IZZI + ZIIZ + ZZII. Setelah operator dibina, ansatz untuk algoritma QAOA boleh dibina dengan mudah menggunakan Circuit QAOAAnsatz daripada pustaka Circuit Qiskit.

from qiskit.circuit.library import QAOAAnsatz
from qiskit.quantum_info import SparsePauliOp

hamiltonian = SparsePauliOp.from_list(
[("IIZZ", 1), ("IZIZ", 1), ("IZZI", 1), ("ZIIZ", 1), ("ZZII", 1)]
)

ansatz = QAOAAnsatz(hamiltonian, reps=2)
# Draw
ansatz.decompose(reps=3).draw("mpl")

Output of the previous code cell

# Sum the weights, and divide by 2

offset = -sum(edge[2] for edge in edges) / 2
print(f"""Offset: {offset}""")
Offset: -2.5

Dengan Estimator Runtime yang secara langsung menerima Hamiltonian dan ansatz berparameter, serta mengembalikan tenaga yang diperlukan, fungsi kos untuk instance QAOA adalah agak mudah:

def cost_func(params, ansatz, hamiltonian, estimator):
"""Return estimate of energy from estimator

Parameters:
params (ndarray): Array of ansatz parameters
ansatz (QuantumCircuit): Parameterized ansatz circuit
hamiltonian (SparsePauliOp): Operator representation of Hamiltonian
estimator (Estimator): Estimator primitive instance

Returns:
float: Energy estimate
"""
pub = (ansatz, hamiltonian, params)
cost = estimator.run([pub]).result()[0].data.evs
# cost = estimator.run(ansatz, hamiltonian, parameter_values=params).result().values[0]
return cost
import numpy as np

x0 = 2 * np.pi * np.random.rand(ansatz.num_parameters)

estimator = StatevectorEstimator()
cost = cost_func_vqe(x0, ansatz, hamiltonian, estimator)
print(cost)
1.473098768180865
# Estimated usage: < 1 min, benchmarked at 6 seconds on ibm_osaka, 5-23-24
# Load some necessary packages:

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import Session, EstimatorV2 as Estimator

# Select the least busy backend:

backend = service.least_busy(
operational=True, min_num_qubits=ansatz.num_qubits, simulator=False
)

# Or get a specific backend:
# backend = service.backend("ibm_brisbane")

# Use a pass manager to transpile the circuit and observable for the specific backend being used:

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_ansatz = pm.run(ansatz)
isa_hamiltonian = hamiltonian.apply_layout(layout=isa_ansatz.layout)

# Set estimator options
estimator_options = EstimatorOptions(resilience_level=1, default_shots=10_000)

# Open a Runtime session:

with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)
cost = cost_func_vqe(x0, isa_ansatz, isa_hamiltonian, estimator)

# Close session after done
session.close()
print(cost)
1.1120776913677988

Kita akan kembali semula kepada contoh ini dalam Aplikasi untuk meneroka cara memanfaatkan pengoptimum untuk berulang melalui ruang carian. Secara umum, ini merangkumi:

  • Memanfaatkan pengoptimum untuk mencari parameter optimum
  • Mengikat parameter optimum kepada ansatz untuk mencari nilai eigen
  • Menterjemahkan nilai eigen kepada definisi masalah kita

Strategi pengukuran: kelajuan berbanding ketepatan

Seperti yang disebutkan, kita menggunakan komputer kuantum yang berdesing sebagai oracle kotak-hitam, di mana bunyi bising boleh menjadikan nilai yang diperolehi tidak deterministik, mengakibatkan turun-naik rawak yang seterusnya akan merosakkan — atau bahkan menghalang sepenuhnya — penumpuan pengoptimum tertentu kepada penyelesaian yang dicadangkan. Ini adalah masalah umum yang perlu kita tangani semasa kita meneroka utiliti kuantum secara berperingkat dan melangkah ke arah kelebihan kuantum:

A graph showing how simulation cost varies with circuit complexity. Using a classical computer it grows exponentially. With quantum error mitigation, there should be a crossover at which that becomes advantageous. Quantum error correction allows for linear growth of the simulation cost and will certainly lead to advantage.

Kita boleh menggunakan pilihan penindasan ralat dan mitigasi ralat dalam Qiskit Runtime Primitive untuk menangani bunyi bising dan memaksimumkan utiliti komputer kuantum hari ini.

Penindasan Ralat

Penindasan ralat merujuk kepada teknik yang digunakan untuk mengoptimumkan dan mengubah Circuit semasa proses kompilasi bagi meminimumkan ralat. Ini adalah teknik pengendalian ralat asas yang biasanya mengakibatkan sedikit overhed pra-pemprosesan klasik kepada masa jalan keseluruhan. Overhed tersebut termasuk transpilasi Circuit untuk dijalankan pada perkakasan kuantum dengan cara:

  • Menyatakan Circuit menggunakan get natif yang tersedia pada sistem kuantum
  • Memetakan Qubit maya kepada Qubit fizikal
  • Menambah SWAP berdasarkan keperluan ketersambungan
  • Mengoptimumkan get 1Q dan 2Q
  • Menambah penguraian dinamik pada Qubit terbiar untuk mencegah kesan dékoheren.

Primitive membolehkan penggunaan teknik penindasan ralat dengan menetapkan pilihan optimization_level dan memilih pilihan transpilasi lanjutan. Dalam kursus seterusnya, kita akan mendalami kaedah pembinaan Circuit yang berbeza untuk meningkatkan keputusan, tetapi bagi kebanyakan kes, kami mengesyorkan untuk menetapkan optimization_level=3.

Kita akan memvisualisasikan nilai peningkatan pengoptimuman dalam proses transpilasi dengan melihat contoh Circuit yang mempunyai tingkah laku ideal yang mudah.

from qiskit.circuit import Parameter, QuantumCircuit
from qiskit.quantum_info import SparsePauliOp

theta = Parameter("theta")

qc = QuantumCircuit(2)
qc.x(1)
qc.h(0)
qc.cp(theta, 0, 1)
qc.h(0)
observables = SparsePauliOp.from_list([("ZZ", 1)])

qc.draw("mpl")

Output of the previous code cell

Circuit di atas boleh menghasilkan nilai jangkaan sinusoidal bagi observable yang diberikan, dengan syarat kita memasukkan fasa yang merentangi selang yang sesuai, seperti [0,2π][0,2\pi].

## Setup phases
import numpy as np

phases = np.linspace(0, 2 * np.pi, 50)

# phases need to be expressed as a list of lists in order to work
individual_phases = [[phase] for phase in phases]

Kita boleh menggunakan simulator untuk menunjukkan kegunaan transpilasi yang dioptimumkan. Kita akan kembali di bawah untuk menggunakan perkakasan sebenar bagi mendemonstrasikan kegunaan mitigasi ralat. Kita akan menggunakan QiskitRuntimeService untuk mendapatkan Backend sebenar (dalam kes ini, ibm_brisbane), dan menggunakan AerSimulator untuk mensimulasikan Backend tersebut, termasuk tingkah laku bunyi bisingnya.

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_aer import AerSimulator

# get a real backend from the runtime service
service = QiskitRuntimeService()
backend = service.backend("ibm_brisbane")

# generate a simulator that mimics the real quantum system with the latest calibration results
backend_sim = AerSimulator.from_backend(backend)

Kita kini boleh menggunakan pass manager untuk mentranspilasi Circuit ke dalam "seni bina set arahan" atau ISA bagi Backend. Ini adalah keperluan baharu dalam Qiskit Runtime: semua Circuit yang diserahkan kepada Backend mesti mematuhi kekangan sasaran Backend, bermakna ia mesti ditulis dalam sebutan ISA Backend — iaitu, set arahan yang boleh difahami dan dilaksanakan oleh peranti. Kekangan sasaran ini ditentukan oleh faktor seperti get asas natif peranti, ketersambungan Qubit-nya, dan — apabila relevan — spesifikasi masa arahan denyut dan lain-lain.

Perhatikan bahawa dalam kes ini, kita akan melakukannya dua kali: sekali dengan optimization_level = 0, dan sekali lagi dengan ia ditetapkan kepada 3. Setiap kali kita akan menggunakan Estimator primitive untuk menganggar nilai jangkaan observable pada nilai fasa yang berbeza.

# Import estimator and specify that we are using the simulated backend:

from qiskit_ibm_runtime import EstimatorV2 as Estimator

estimator = Estimator(mode=backend_sim)

circuit = qc
# Use a pass manager to transpile the circuit and observable for the backend being simulated.
# Start with no optimization:

from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

pm = generate_preset_pass_manager(backend=backend_sim, optimization_level=0)
isa_circuit = pm.run(circuit)
isa_observables = observables.apply_layout(layout=isa_circuit.layout)

noisy_exp_values = []
pub = (isa_circuit, isa_observables, [individual_phases])
cost = estimator.run([pub]).result()[0].data.evs
noisy_exp_values = cost[0]

# Repeat above steps, but now with optimization = 3:

exp_values_with_opt_es = []
pm = generate_preset_pass_manager(backend=backend_sim, optimization_level=3)
isa_circuit = pm.run(circuit)
isa_observables = observables.apply_layout(layout=isa_circuit.layout)

pub = (isa_circuit, isa_observables, [individual_phases])
cost = estimator.run([pub]).result()[0].data.evs
exp_values_with_opt_es = cost[0]

Akhirnya, kita boleh memplot keputusan, dan kita dapat melihat bahawa ketepatan pengiraan agak baik walaupun tanpa pengoptimuman, tetapi ia sememangnya bertambah baik dengan meningkatkan pengoptimuman ke tahap 3. Perhatikan bahawa dalam Circuit yang lebih dalam dan lebih rumit, perbezaan antara tahap pengoptimuman 0 dan 3 berkemungkinan lebih ketara. Ini adalah Circuit yang sangat mudah yang digunakan sebagai model mainan.

import matplotlib.pyplot as plt

plt.plot(phases, noisy_exp_values, "o", label="opt=0")
plt.plot(phases, exp_values_with_opt_es, "o", label="opt=3")
plt.plot(phases, 2 * np.sin(phases / 2) ** 2 - 1, label="ideal")
plt.ylabel("Expectation")
plt.legend()
plt.show()

Output of the previous code cell

Mitigasi Ralat

Mitigasi ralat merujuk kepada teknik yang membolehkan pengguna mengurangkan ralat Circuit dengan memodelkan bunyi bising peranti pada masa pelaksanaan. Biasanya, ini mengakibatkan overhed pra-pemprosesan kuantum berkaitan latihan model dan overhed pasca-pemprosesan klasik untuk memitigasi ralat dalam keputusan mentah menggunakan model yang dijana.

Pilihan resilience_level dalam Qiskit Runtime primitive menentukan tahap daya tahan terhadap ralat yang hendak dibina. Tahap yang lebih tinggi menghasilkan keputusan yang lebih tepat dengan mengorbankan masa pemprosesan yang lebih lama akibat overhed pensampelan kuantum. Tahap daya tahan boleh digunakan untuk mengkonfigurasi pertukaran antara kos dan ketepatan apabila menggunakan mitigasi ralat pada pertanyaan primitive anda.

Apabila melaksanakan mana-mana teknik mitigasi ralat, kita mengharapkan bias dalam keputusan kita berkurangan berbanding bias yang tidak dimitigasi sebelumnya. Dalam sesetengah kes, bias mungkin hilang sepenuhnya. Namun, ini ada kosnya. Semasa kita mengurangkan bias dalam kuantiti anggaran kita, kebolehubahan statistik akan meningkat (iaitu, varians), yang boleh kita akaunkan dengan meningkatkan lagi bilangan shot per Circuit dalam proses pensampelan kita. Ini akan memperkenalkan overhed melebihi yang diperlukan untuk mengurangkan bias, jadi ia tidak dilakukan secara lalai. Kita boleh memilih tingkah laku ini dengan mudah dengan melaraskan bilangan shot per Circuit dalam options.executions.shots, seperti yang ditunjukkan dalam contoh di bawah.

A diagram showing broader or narrowing distributions as in the bias/variance tradeoff.

Untuk kursus ini, kita akan meneroka model mitigasi ralat ini pada tahap tinggi untuk menggambarkan mitigasi ralat yang boleh dilakukan oleh Qiskit Runtime primitive tanpa memerlukan butiran pelaksanaan penuh.

Pemadaman ralat baca semula berpintal (T-REx)

Pemadaman ralat baca semula berpintal (T-REx) menggunakan teknik yang dikenali sebagai pelilitan Pauli untuk mengurangkan bunyi bising yang diperkenalkan semasa proses pengukuran kuantum. Teknik ini tidak mengandaikan sebarang bentuk bunyi bising tertentu, menjadikannya sangat umum dan berkesan.

Aliran kerja keseluruhan:

  1. Dapatkan data untuk keadaan sifar dengan pembalikan bit rawak (Pauli X sebelum pengukuran)
  2. Dapatkan data untuk keadaan yang dikehendaki (berdesing) dengan pembalikan bit rawak (Pauli X sebelum pengukuran)
  3. Kira fungsi khas untuk setiap set data, dan bahagikan.

 

A diagram showing measurement and calibration circuits for T-REX.

Kita boleh menetapkan ini dengan options.resilience_level = 1, seperti yang ditunjukkan dalam contoh di bawah.

Ekstrapolasi sifar bunyi bising

Ekstrapolasi sifar bunyi bising (ZNE) berfungsi dengan terlebih dahulu memperkuatkan bunyi bising dalam Circuit yang menyediakan keadaan kuantum yang dikehendaki, memperoleh pengukuran untuk beberapa tahap bunyi bising yang berbeza, dan menggunakan pengukuran tersebut untuk membuat kesimpulan tentang keputusan tanpa bunyi bising.

Aliran kerja keseluruhan:

  1. Perkuatkan bunyi bising Circuit untuk beberapa faktor bunyi bising
  2. Jalankan setiap Circuit yang telah diperkuatkan bunyi bisingnya
  3. Ekstrapolasi kembali ke had sifar bunyi bising

 

A diagram showing steps in ZNE. Noise is artificially amplified by different factors. Then the values are extrapolated to what they should be at zero noise.

Kita boleh menetapkan ini dengan options.resilience_level = 2. Kita boleh mengoptimumkan ini lebih lanjut dengan meneroka pelbagai noise_factors, noise_amplifiers, dan extrapolators, tetapi ini di luar skop kursus ini. Kami menggalakkan anda untuk bereksperimen dengan pilihan-pilihan ini seperti yang dihuraikan di sini.

Setiap kaedah datang dengan overhed yang berbeza: pertukaran antara bilangan pengiraan kuantum yang diperlukan (masa) dan ketepatan keputusan kita:

MethodsR=1, T-RExR=2, ZNEAssumptionsNoneAbility to scale noiseQubit overhead11Sampling overhead2Nnoise-factorsBias0O(λNnoise-factors)\begin{array}{c|c|c|c} \text{Methods} & R=1 \text{, T-REx} & R=2 \text{, ZNE} \\[1mm] \hline \text{Assumptions} & \text{None} & \text{Ability to scale noise} \\[1mm] \text{Qubit overhead} & 1 & 1 \\[1mm] \text{Sampling overhead} & 2 & N_{\text{noise-factors}} \\[1mm] \text{Bias} & 0 & \mathcal{O}(\lambda^{N_{\text{noise-factors}}}) \\[1mm] \end{array}

Menggunakan pilihan mitigasi dan penindasan Qiskit Runtime

Berikut adalah cara untuk mengira nilai jangkaan sambil menggunakan mitigasi ralat dan penindasan dalam Qiskit Runtime. Kita boleh menggunakan Circuit dan observable yang sama seperti sebelumnya, tetapi kali ini memastikan tahap pengoptimuman tetap pada tahap 2, dan kini menala daya tahan atau teknik mitigasi ralat yang digunakan. Proses mitigasi ralat ini berlaku beberapa kali sepanjang gelung pengoptimuman.

Kita menjalankan bahagian ini pada perkakasan sebenar, kerana mitigasi ralat tidak tersedia pada simulator.

# Estimated usage: 8 minutes, benchmarked on an Eagle processor, 5-23-24

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import (
Session,
EstimatorOptions,
EstimatorV2 as Estimator,
)

# We select the least busy backend

# Select the least busy backend
# backend = service.least_busy(
# operational=True, min_num_qubits=ansatz.num_qubits, simulator=False
# )

# Or use a specific backend
backend = service.backend("ibm_brisbane")

# Initialize some variables to save the results from different runs:

exp_values_with_em0_es = []
exp_values_with_em1_es = []
exp_values_with_em2_es = []

# Use a pass manager to optimize the circuit and observables for the backend chosen:

pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
isa_circuit = pm.run(circuit)
isa_observables = observables.apply_layout(layout=isa_circuit.layout)

# Open a session and run with no error mitigation:

estimator_options = EstimatorOptions(resilience_level=0, default_shots=10_000)

with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)

pub = (isa_circuit, isa_observables, [individual_phases])
cost = estimator.run([pub]).result()[0].data.evs

session.close()

exp_values_with_em0_es = cost[0]

# Open a session and run with resilience = 1:

estimator_options = EstimatorOptions(resilience_level=1, default_shots=10_000)

with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)

pub = (isa_circuit, isa_observables, [individual_phases])
cost = estimator.run([pub]).result()[0].data.evs

session.close()

exp_values_with_em1_es = cost[0]

# Open a session and run with resilience = 2:

estimator_options = EstimatorOptions(resilience_level=2, default_shots=10_000)

with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)

pub = (isa_circuit, isa_observables, [individual_phases])
cost = estimator.run([pub]).result()[0].data.evs

session.close()

exp_values_with_em2_es = cost[0]

Seperti sebelumnya, kita boleh memplot nilai jangkaan yang terhasil sebagai fungsi sudut fasa untuk tiga tahap mitigasi ralat yang digunakan. Dengan susah payah, seseorang dapat melihat bahawa mitigasi ralat meningkatkan keputusan sedikit. Sekali lagi, kesan ini jauh lebih ketara dalam Circuit yang lebih dalam dan lebih rumit.

import matplotlib.pyplot as plt

plt.plot(phases, exp_values_with_em0_es, "o", label="unmitigated")
plt.plot(phases, exp_values_with_em1_es, "o", label="resil = 1")
plt.plot(phases, exp_values_with_em2_es, "o", label="resil = 2")
plt.plot(phases, 2 * np.sin(phases / 2) ** 2 - 1, label="ideal")
plt.ylabel("Expectation")
plt.legend()
plt.show()

Output of the previous code cell

Ringkasan

Dengan pelajaran ini, anda telah belajar cara mencipta fungsi kos:

  • Cipta fungsi kos
  • Cara memanfaatkan Qiskit Runtime primitive untuk memitigasi dan menindas bunyi bising
  • Cara menentukan strategi pengukuran untuk mengoptimumkan kelajuan berbanding ketepatan

Berikut adalah beban kerja variasi tahap tinggi kita:

A diagram showing the quantum circuit with unitaries preparing the reference state and variational state, followed by measurements. These are used to evaluate the cost function.

Fungsi kos kita berjalan pada setiap lelaran gelung pengoptimuman. Pelajaran seterusnya akan meneroka cara pengoptimum klasik menggunakan penilaian fungsi kos kita untuk memilih parameter baharu.

import qiskit
import qiskit_ibm_runtime

print(qiskit.version.get_version_info())
print(qiskit_ibm_runtime.version.get_version_info())
1.1.0
0.23.0
Source: IBM Quantum docs — updated 5 Mei 2026
English version on doQumentation — updated 7 Mei 2026
This translation based on the English version of approx. 27 Mac 2026