انتقل إلى المحتوى الرئيسي

نماذج وامتدادات

يغطي هذا الفصل عدة خوارزميات كمية تبايُنية، من بينها:

من خلال استخدام هذه الخوارزميات، ستتعلم عدة أفكار تصميمية يمكن دمجها في خوارزميات تبايُنية مخصصة، مثل: الأوزان، والعقوبات، والمعاينة الزائدة، والمعاينة الناقصة. نشجعك على التجربة مع هذه المفاهيم ومشاركة نتائجك مع المجتمع.

يسري إطار أنماط Qiskit على جميع هذه الخوارزميات — غير أننا سنستدعي الخطوات صراحةً في المثال الأول فقط.

محلّل القيم الذاتية الكمي التبايُني (VQE)

VQE هو أحد أكثر خوارزميات الكم التبايُنية استخدامًا، إذ يضع قالبًا تبني عليه خوارزميات أخرى.

مخطط يوضح كيف يستخدم VQE الحالة المرجعية و الأنزاتز لتقدير دالة التكلفة، ثم التكرار باستخدام المعاملات التبايُنية.

الخطوة 1: تحويل المدخلات الكلاسيكية إلى مسألة كمية

التصميم النظري

تصميم VQE بسيط:

  • تحضير المؤثرات المرجعية URU_R
    • نبدأ من الحالة 0|0\rangle وننتقل إلى الحالة المرجعية ρ|\rho\rangle
  • تطبيق الشكل التبايُني UV(θi,j)U_V(\vec\theta_{i,j}) لإنشاء الأنزاتز UA(θi,j)U_A(\vec\theta_{i,j})
    • ننتقل من الحالة ρ|\rho\rangle إلى UV(θi,j)ρ=ψ(θi,j)U_V(\vec\theta_{i,j})|\rho\rangle = |\psi(\vec\theta_{i,j})\rangle
  • التمهيد عند i=0i=0 إذا كان لدينا مسألة مشابهة (تُوجَد عادةً عبر المحاكاة الكلاسيكية أو أخذ العينات)
    • سيتمهّد كل مُحسِّن بطريقة مختلفة، مما ينتج عنه مجموعة أولية من متجهات المعاملات Θ0:=θ0,jjJopt0\Theta_0 := \\{ {\vec\theta_{0,j} | j \in \mathcal{J}_\text{opt}^0} \\} (مثلًا، من نقطة أولية θ0\vec\theta_0).
  • حساب دالة التكلفة C(θi,j):=ψ(θ)H^ψ(θ)C(\vec\theta_{i,j}) := \langle \psi(\vec{\theta}) | \hat{H} | \psi(\vec{\theta})\rangle لجميع الحالات المُعدَّة على حاسوب كمي.
  • استخدام مُحسِّن كلاسيكي لاختيار المجموعة التالية من المعاملات Θi+1\Theta_{i+1}.
  • تكرار العملية حتى الوصول إلى التقارب.

هذه حلقة تحسين كلاسيكية بسيطة نحسب فيها دالة التكلفة. قد يتطلب بعض المحسِّنات تقييمات متعددة لحساب التدرج، أو تحديد التكرار التالي، أو تقييم التقارب.

إليك المثال للمتغير التالي:

O^1=2II2XX+3YY3ZZ,\hat{O}_1 = 2 II - 2 XX + 3 YY - 3 ZZ,

التنفيذ

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime scipy
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.circuit.library import TwoLocal
import numpy as np

theta_list = (2 * np.pi * np.random.rand(1, 8)).tolist()
observable = SparsePauliOp.from_list([("II", 2), ("XX", -2), ("YY", 3), ("ZZ", -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)

ansatz.decompose().draw("mpl")

مخرجات خلية الكود السابقة

def cost_func_vqe(parameters, 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
"""

estimator_job = estimator.run([(ansatz, hamiltonian, [parameters])])
estimator_result = estimator_job.result()[0]

cost = estimator_result.data.evs[0]
return cost
from qiskit.primitives import StatevectorEstimator

estimator = StatevectorEstimator()

يمكننا استخدام دالة التكلفة هذه لحساب المعاملات المثلى

# SciPy minimizer routine
from scipy.optimize import minimize

x0 = np.ones(8)

result = minimize(
cost_func_vqe, x0, args=(ansatz, observable, estimator), method="COBYLA"
)

result
message: Optimization terminated successfully.
success: True
status: 1
fun: -5.999999982445723
x: [ 1.741e+00 9.606e-01 1.571e+00 2.115e-05 1.899e+00
1.243e+00 6.063e-01 6.063e-01]
nfev: 136
maxcv: 0.0

الخطوة 2: تحسين المسألة للتنفيذ الكمي

سنختار الخلفية الأقل انشغالًا، ونستورد المكوّنات الضرورية من qiskit_ibm_runtime.

from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime import Session, EstimatorOptions
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
print(backend)
<IBMBackend('ibm_brisbane')>

سنُحوِّل الدائرة باستخدام مدير التمريرات المُعدَّ مسبقًا بمستوى التحسين 3، ونُطبّق التخطيط المقابل على المتغير.

from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

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

الخطوة 3: التنفيذ باستخدام بدائيات Qiskit Runtime

نحن الآن جاهزون لتشغيل حساباتنا على عتاد IBM Quantum®. نظرًا لأن تقليل دالة التكلفة يتضمن تكرارات كثيرة، سنبدأ جلسة Runtime. بهذه الطريقة، ننتظر في قائمة الانتظار مرة واحدة فقط. بمجرد بدء تشغيل المهمة، ستعمل كل تكرارة بتحديثات للمعاملات فورًا.

x0 = np.ones(8)

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

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

result = minimize(
cost_func_vqe,
x0,
args=(isa_ansatz, isa_observable, estimator),
method="COBYLA",
options={"maxiter": 200, "disp": True},
)
session.close()
print(result)

الخطوة 4: المعالجة اللاحقة وإعادة النتيجة بالصيغة الكلاسيكية

يمكننا أن نرى أن روتين التقليل انتهى بنجاح، مما يعني وصولنا إلى التسامح الافتراضي للمحسِّن الكلاسيكي COBYLA. إذا أردنا نتيجة أدق، يمكننا تحديد تسامح أصغر. قد يكون ذلك ضروريًا فعلًا، إذ جاءت النتيجة مختلفة بنسبة بضعة بالمئة مقارنةً بنتيجة المحاكاة أعلاه.

القيمة x المُتحصَّل عليها هي أفضل تخمين حالي للمعاملات التي تُصغِّر دالة التكلفة. عند التكرار للحصول على دقة أعلى، يجب استخدام تلك القيم بدلًا من x0 المُستخدمة في البداية (متجه من الواحدات).

وأخيرًا، نلاحظ أن الدالة قُيِّمت 96 مرة خلال عملية التحسين. قد يختلف ذلك عن عدد خطوات التحسين، إذ يتطلب بعض المحسِّنات تقييمات متعددة في خطوة واحدة، كما هو الحال عند تقدير التدرج.

VQE بالبحث في الفضاء الجزئي (SSVQE)

SSVQE هو متغيّر من VQE يتيح الحصول على أول kk قيم ذاتية لمتغيّر H^\hat{H} ذات قيم ذاتية {λ0,λ1,...,λN1}\{\lambda_0, \lambda_1,...,\lambda_{N-1}\}، حيث NkN\geq k. دون فقدان العمومية، نفترض أن λ0<λ1<...<λN1\lambda_0<\lambda_1<...<\lambda_{N-1}. يُدخل SSVQE فكرة جديدة بإضافة أوزان للمساعدة في إعطاء الأولوية لتحسين الحد ذي الوزن الأكبر.

مخطط يوضح كيف يستخدم VQE بالبحث في الفضاء الجزئي مكوّنات الخوارزمية التبايُنية.

لتنفيذ هذه الخوارزمية، نحتاج إلى kk حالة مرجعية متعامدة بالتبادل {ρj}j=0k1\{ |\rho_j\rangle \}_{j=0}^{k-1}، بمعنى ρjρl=δjl\langle \rho_j | \rho_l \rangle = \delta_{jl} لـ j,l<kj,l<k. يمكن بناء هذه الحالات باستخدام مؤثرات باولي. دالة التكلفة لهذه الخوارزمية هي:

C(θ):=j=0k1wjρjUV(θ)H^UV(θ)ρj:=j=0k1wjψj(θ)H^ψj(θ)\begin{aligned} C(\vec{\theta}) & := \sum_{j=0}^{k-1} w_j \langle \rho_j | U_{V}^{\dagger}(\vec{\theta})\hat{H} U_{V}(\vec{\theta})|\rho_j \rangle \\[1mm] & := \sum_{j=0}^{k-1} w_j \langle \psi_{j}(\vec{\theta}) | \hat{H} | \psi_{j}(\vec{\theta}) \rangle \\[1mm] \end{aligned}

حيث wjw_j عدد موجب اعتباطي بحيث إذا كان j<l<kj<l<k فإن wj>wlw_j>w_l، وUV(θ)U_V(\vec{\theta}) هو الشكل التبايُني المُعرَّف من قِبَل المستخدم.

تعتمد خوارزمية SSVQE على حقيقة أن الحالات الذاتية المقابلة لقيم ذاتية مختلفة تكون متعامدة بالتبادل. تحديدًا، يمكن التعبير عن الضرب الداخلي لـ UV(θ)ρjU_V(\vec{\theta})|\rho_j\rangle و UV(θ)ρlU_V(\vec{\theta})|\rho_l\rangle كما يلي:

ρjUV(θ)UV(θ)ρl=ρjIρl=ρjρl=δjl\begin{aligned} \langle \rho_j | U_{V}^{\dagger}(\vec{\theta})U_{V}(\vec{\theta})|\rho_l \rangle & = \langle \rho_j | I |\rho_l \rangle \\[1mm] & = \langle \rho_j | \rho_l \rangle \\[1mm] & = \delta_{jl} \end{aligned}

تصح المساواة الأولى لأن UV(θ)U_{V}(\vec{\theta}) مؤثر كمي وبالتالي أحادي. تصح المساواة الأخيرة بسبب تعامد الحالات المرجعية ρj|\rho_j\rangle. حفاظ التحويلات الأحادية على التعامد مرتبط ارتباطًا وثيقًا بمبدأ حفظ المعلومات كما يُعبَّر عنه في علم معلومات الكم. من هذا المنظور، تُمثّل التحويلات غير الأحادية عمليات يُفقد فيها المعلومات أو تُضخَّ.

تساعد الأوزان wjw_j على ضمان أن جميع الحالات هي حالات ذاتية. إذا كانت الأوزان مختلفة بما يكفي، فسيُعطى الأولوية للحد ذي الوزن الأكبر (أي w0w_0) أثناء التحسين على غيره. ونتيجةً لذلك، ستصبح الحالة UV(θ)ρ0U_{V}(\vec{\theta})|\rho_0 \rangle هي الحالة الذاتية المقابلة لـ λ0\lambda_0. ولأن {UV(θ)ρj}j=0k1\{ U_{V}(\vec{\theta})|\rho_j\rangle \}_{j=0}^{k-1} تعامدية بالتبادل، ستكون الحالات المتبقية متعامدة معها، وبالتالي محتواة في الفضاء الجزئي المقابل للقيم الذاتية {λ1,...,λN1}\{\lambda_1,...,\lambda_{N-1}\}.

بتطبيق نفس المنطق على بقية الحدود، فإن الأولوية التالية ستكون للحد ذي الوزن w1w_1، وبالتالي ستكون UV(θ)ρ1U_{V}(\vec{\theta})|\rho_1 \rangle هي الحالة الذاتية المقابلة لـ λ1\lambda_1، وستكون الحدود الأخرى محتواة في الفضاء الذاتي لـ {λ2,...,λN1}\{\lambda_2,...,\lambda_{N-1}\}.

باستخدام الاستنتاج الاستقرائي، نستنتج أن UV(θ)ρjU_{V}(\vec{\theta})|\rho_j \rangle ستكون حالة ذاتية تقريبية لـ λj\lambda_j لكل 0j<k0\leq j < k.

التصميم النظري

يمكن تلخيص SSVQE كما يلي:

  • تحضير عدة حالات مرجعية بتطبيق وحدوي U_R على k حالة مختلفة من حالات الأساس الحسابي
    • تتطلب هذه الخوارزمية استخدام kk حالة مرجعية متعامدة بالتبادل {ρj}j=0k1\{ |\rho_j\rangle \}_{j=0}^{k-1}، بحيث ρjρl=δjl\langle \rho_j | \rho_l \rangle = \delta_{jl} لـ j,l<kj,l<k.
  • تطبيق الشكل التبايُني UV(θi,j)U_V(\vec\theta_{i,j}) على كل حالة مرجعية، مما ينتج الأنزاتز UA(θi,j)U_A(\vec\theta_{i,j}).
  • التمهيد عند i=0i=0 إذا كانت مسألة مشابهة متاحة (تُوجَد عادةً عبر المحاكاة الكلاسيكية أو أخذ العينات).
  • حساب دالة التكلفة C(θi,j):=j=0k1wjψj(θ)H^ψj(θ)C(\vec\theta_{i,j}) := \sum_{j=0}^{k-1} w_j \langle \psi_{j}(\vec{\theta}) | \hat{H} | \psi_{j}(\vec{\theta}) \rangle لجميع الحالات المُعدَّة على حاسوب كمي.
    • يمكن تقسيم ذلك إلى حساب قيمة التوقع لمتغيّر ψj(θ)H^ψj(θ)\langle \psi_{j}(\vec{\theta}) | \hat{H} | \psi_{j}(\vec{\theta}) \rangle وضرب النتيجة في wjw_j.
    • بعد ذلك، تُعيد دالة التكلفة مجموع جميع قيم التوقع الموزونة.
  • استخدام مُحسِّن كلاسيكي لتحديد المجموعة التالية من المعاملات Θi+1\Theta_{i+1}.
  • تكرار الخطوات السابقة حتى تحقق التقارب.

ستُعيد بناء دالة تكلفة SSVQE في التقييم، لكننا نقدم المقطع التالي لتحفيز حلّك:

import numpy as np

def cost_func_ssvqe(
params, initialized_anastz_list, weights, ansatz, hamiltonian, estimator
):
# """Return estimate of energy from estimator

# Parameters:
# params (ndarray): Array of ansatz parameters
# initialized_anastz_list (list QuantumCircuit): Array of initialised ansatz with reference
# weights (list): List of weights
# ansatz (QuantumCircuit): Parameterized ansatz circuit
# hamiltonian (SparsePauliOp): Operator representation of Hamiltonian
# estimator (Estimator): Estimator primitive instance

# Returns:
# float: Weighted energy estimate
# """

energies = []

# Define SSVQE

weighted_energy_sum = np.dot(energies, weights)
return weighted_energy_sum

الانحراف الكمي التبايُني (VQD)

VQD هو أسلوب تكراري يمتد على VQE للحصول على أول kk قيم ذاتية لمتغيّر H^\hat{H} ذات قيم ذاتية {λ0,λ1,...,λN1}\{\lambda_0, \lambda_1,...,\lambda_{N-1}\}، حيث NkN\geq k، بدلًا من الحصول على الأولى فقط. في بقية هذا القسم، سنفترض دون فقدان العمومية أن λ0λ1...λN1\lambda_0\leq\lambda_1\leq...\leq\lambda_{N-1}. يُدخل VQD مفهوم تكلفة العقوبة لتوجيه عملية التحسين.

مخطط يوضح كيف يستخدم VQD مكوّنات الخوارزمية التبايُنية.

يُدخل VQD حدًّا للعقوبة يُرمز له بـ β\beta، لموازنة إسهام كل حد تداخل في التكلفة. يُعاقب هذا الحد عملية التحسين إذا لم يتحقق التعامد. نفرض هذا القيد لأن الحالات الذاتية لمتغيّر ما، أو مؤثر هيرميتي، المقابلة لقيم ذاتية مختلفة تكون دائمًا متعامدة بالتبادل، أو يمكن جعلها كذلك في حالة التعدد أو تكرار القيم الذاتية. وبالتالي، بفرض التعامد مع الحالة الذاتية المقابلة لـ λ0\lambda_0، نُحسِّن فعليًا في الفضاء الجزئي المقابل لبقية القيم الذاتية {λ1,λ2,...,λN1}\{\lambda_1, \lambda_2,..., \lambda_{N-1}\}. هنا، λ1\lambda_1 هي أصغر قيمة ذاتية من بقية القيم الذاتية، وبالتالي يمكن الحصول على الحل الأمثل للمسألة الجديدة باستخدام المبرهنة التبايُنية.

الفكرة العامة وراء VQD هي استخدام VQE كالمعتاد للحصول على أصغر قيمة ذاتية λ0:=C0(θ0)CVQE(θ0)\lambda_0 := C_0(\vec\theta^0) \equiv C_\text{VQE}(\vec\theta^0) مع الحالة الذاتية (التقريبية) المقابلة ψ(θ0)|\psi(\vec{\theta^0})\rangle لمتجه معاملات مثلى θ0\vec{\theta^0}. ثم للحصول على القيمة الذاتية التالية λ1>λ0\lambda_1 > \lambda_0، بدلًا من تصغير دالة التكلفة C0(θ):=ψ(θ)H^ψ(θ)C_0(\vec{\theta}) := \langle \psi(\vec{\theta}) | \hat{H} | \psi(\vec{\theta})\rangle، نحسِّن:

C1(θ):=C0(θ)+β0ψ(θ)ψ(θ0)2C_1(\vec{\theta}) := C_0(\vec{\theta})+ \beta_0 |\langle \psi(\vec{\theta})| \psi(\vec{\theta^0})\rangle |^2

يجب أن تكون القيمة الموجبة β0\beta_0 مثاليًا أكبر من λ1λ0\lambda_1-\lambda_0.

هذا يُدخل دالة تكلفة جديدة يمكن النظر إليها كمسألة مُقيَّدة، حيث نُصغِّر CVQE(θ)=ψ(θ)H^ψ(θ)C_\text{VQE}(\vec{\theta}) = \langle \psi(\vec{\theta}) | \hat{H} | \psi(\vec{\theta})\rangle مع قيد أن الحالة يجب أن تكون متعامدة مع ψ(θ0)|\psi(\vec{\theta^0})\rangle المُتحصَّل عليها سابقًا، مع عمل β0\beta_0 كحد عقوبة إذا لم يُستوفَ القيد.

بدلًا من ذلك، يمكن تفسير هذه المسألة الجديدة على أنها تشغيل VQE على المتغيّر الجديد:

H1^:=H^+β0ψ(θ0)ψ(θ0)C1(θ)=ψ(θ)H1^ψ(θ),\hat{H_1} := \hat{H} + \beta_0 |\psi(\vec{\theta^0})\rangle \langle \psi(\vec{\theta^0})| \quad \Rightarrow \quad C_1(\vec{\theta}) = \langle \psi(\vec{\theta}) | \hat{H_1} | \psi(\vec{\theta})\rangle,

بافتراض أن حل المسألة الجديدة هو ψ(θ1)|\psi(\vec{\theta^1})\rangle، يجب أن تكون القيمة المتوقعة لـ H^\hat{H} (وليس H1^\hat{H_1}) هي ψ(θ1)H^ψ(θ1)=λ1 \langle \psi(\vec{\theta^1}) | \hat{H} | \psi(\vec{\theta^1})\rangle = \lambda_1.

للحصول على القيمة الذاتية الثالثة λ2\lambda_2، دالة التكلفة المراد تحسينها هي:

C2(θ):=C1(θ)+β1ψ(θ)ψ(θ1)2C_2(\vec{\theta}) := C_1(\vec{\theta}) + \beta_1 |\langle \psi(\vec{\theta})| \psi(\vec{\theta^1})\rangle |^2

حيث β1\beta_1 ثابت موجب كبير بما يكفي لفرض تعامد الحالة الحلية مع كل من ψ(θ0)|\psi(\vec{\theta^0})\rangle وψ(θ1)|\psi(\vec{\theta^1})\rangle. يُعاقب هذا الحالات في فضاء البحث التي لا تستوفي هذا الشرط، مما يقيّد فضاء البحث فعليًا. وبالتالي، يجب أن يكون الحل الأمثل للمسألة الجديدة هو الحالة الذاتية المقابلة لـ λ2\lambda_2.

كما في الحالة السابقة، يمكن أيضًا تفسير هذه المسألة الجديدة كـ VQE مع المتغيّر:

H2^:=H1^+β1ψ(θ1)ψ(θ1)C2(θ)=ψ(θ)H2^ψ(θ).\hat{H_2} := \hat{H_1} + \beta_1 |\psi(\vec{\theta^1})\rangle \langle \psi(\vec{\theta^1})| \quad \Rightarrow \quad C_2(\vec{\theta}) = \langle \psi(\vec{\theta}) | \hat{H_2} | \psi(\vec{\theta})\rangle.

إذا كان حل هذه المسألة الجديدة هو ψ(θ2)|\psi(\vec{\theta^2})\rangle، يجب أن تكون القيمة المتوقعة لـ H^\hat{H} (وليس H2^\hat{H_2}) هي ψ(θ2)H^ψ(θ2)=λ2 \langle \psi(\vec{\theta^2}) | \hat{H} | \psi(\vec{\theta^2})\rangle = \lambda_2.

وبالمماثلة، للحصول على القيمة الذاتية kk-ية λk1\lambda_{k-1}، تُصغِّر دالة التكلفة:

Ck1(θ):=Ck2(θ)+βk2ψ(θ)ψ(θk2)2,C_{k-1}(\vec{\theta}) := C_{k-2}(\vec{\theta}) + \beta_{k-2} |\langle \psi(\vec{\theta})| \psi(\vec{\theta^{k-2}})\rangle |^2,

تذكّر أننا عرّفنا θj\vec{\theta^j} بحيث ψ(θj)H^ψ(θj)=λj,j<k\langle \psi(\vec{\theta^j}) | \hat{H} | \psi(\vec{\theta^j})\rangle = \lambda_j, \forall j<k. هذه المسألة تعادل تصغير C(θ)=ψ(θ)H^ψ(θ)C(\vec{\theta}) = \langle \psi(\vec{\theta}) | \hat{H} | \psi(\vec{\theta})\rangle مع قيد أن الحالة يجب أن تكون متعامدة مع ψ(θj);j0,,k1|\psi(\vec{\theta^j})\rangle ; \forall j \in {0, \cdots, k-1}، مما يقيّد فضاء البحث على الفضاء الجزئي المقابل للقيم الذاتية {λk1,,λN1}\{\lambda_{k-1},\cdots,\lambda_{N-1}\}.

هذه المسألة تعادل VQE مع المتغيّر:

H^k1:=H^k2+βk2ψ(θk2)ψ(θk2)Ck1(θ)=ψ(θ)H^k1ψ(θ),\hat{H}_{k-1} := \hat{H}_{k-2} + \beta_{k-2} |\psi(\vec{\theta^{k-2}})\rangle \langle \psi(\vec{\theta^{k-2}})| \quad \Rightarrow \quad C_{k-1}(\vec{\theta}) = \langle \psi(\vec{\theta}) | \hat{H}_{k-1} | \psi(\vec{\theta})\rangle,

كما يتضح من العملية، للحصول على القيمة الذاتية kk-ية، تحتاج إلى الحالات الذاتية (التقريبية) للقيم الذاتية الـ k1k-1 السابقة، وبالتالي ستحتاج إلى تشغيل VQE إجمالًا kk مرات. لذلك، دالة تكلفة VQD هي:

Ck(θ)=ψ(θ)H^ψ(θ)+j=0k1βjψ(θ)ψ(θj)2C_k(\vec{\theta}) = \langle \psi(\vec{\theta}) | \hat{H} | \psi(\vec{\theta})\rangle + \sum_{j=0}^{k-1}\beta_j |\langle \psi(\vec{\theta})| \psi(\vec{\theta^j})\rangle |^2

التصميم النظري

يمكن تلخيص تصميم VQD كما يلي:

  • تحضير مؤثر مرجعي URU_R
  • تطبيق الشكل التبايُني UV(θi,j)U_V(\vec\theta_{i,j}) على الحالة المرجعية، مما ينتج الأنزاتزات UA(θi,j)U_A(\vec\theta_{i,j})
  • التمهيد عند i=0i=0 إذا كان لدينا مسألة مشابهة (تُوجَد عادةً عبر المحاكاة الكلاسيكية أو أخذ العينات).
  • حساب دالة التكلفة Ck(θ)C_k(\vec{\theta})، والتي تتضمن حساب kk حالات متحمِّسة ومصفوفة من β\beta's تحدد عقوبة التداخل لكل حد تداخل.
    • حساب قيمة التوقع لمتغيّر ψj(θ)H^ψj(θ)\langle \psi_{j}(\vec{\theta}) | \hat{H} | \psi_{j}(\vec{\theta}) \rangle لكل kk
    • حساب العقوبة j=0k1βjψ(θ)ψ(θj)2\sum_{j=0}^{k-1}\beta_j |\langle \psi(\vec{\theta})| \psi(\vec{\theta^j})\rangle |^2.
    • يجب على دالة التكلفة إعادة مجموع هذين الحدين
  • استخدام مُحسِّن كلاسيكي لاختيار المجموعة التالية من المعاملات Θi+1\Theta_{i+1}.
  • تكرار هذه العملية حتى تحقق التقارب.

التنفيذ

في هذا التنفيذ، سننشئ دالة لعقوبة التداخل. ستُستخدم هذه العقوبة في دالة التكلفة عند كل تكرارة. ستُكرَّر هذه العملية لكل حالة متحمِّسة.

from qiskit.circuit.library import TwoLocal

ansatz = TwoLocal(2, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)

ansatz.decompose().draw("mpl")

مخرجات خلية الكود السابقة

أولًا، سننشئ دالة تحسب أمانة الحالة — نسبة التداخل بين حالتين سنستخدمها كعقوبة لـ VQD:

import numpy as np

def calculate_overlaps(ansatz, prev_circuits, parameters, sampler):
def create_fidelity_circuit(circuit_1, circuit_2):
"""
Constructs the list of fidelity circuits to be evaluated.
These circuits represent the state overlap between pairs of input circuits,
and their construction depends on the fidelity method implementations.
"""

if len(circuit_1.clbits) > 0:
circuit_1.remove_final_measurements()
if len(circuit_2.clbits) > 0:
circuit_2.remove_final_measurements()

circuit = circuit_1.compose(circuit_2.inverse())
circuit.measure_all()
return circuit

overlaps = []

for prev_circuit in prev_circuits:
fidelity_circuit = create_fidelity_circuit(ansatz, prev_circuit)
sampler_job = sampler.run([(fidelity_circuit, parameters)])
meas_data = sampler_job.result()[0].data.meas

counts_0 = meas_data.get_int_counts().get(0, 0)
shots = meas_data.num_shots
overlap = counts_0 / shots
overlaps.append(overlap)

return np.array(overlaps)

حان الوقت لكتابة دالة تكلفة VQD. كما فعلنا عند حساب حالة الأساس فقط، سنحدد حالة أدنى طاقة باستخدام البدائي Estimator. غير أنه، كما هو موضح أعلاه، سنضيف الآن حد عقوبة لضمان تعامد الحالات ذات الطاقات الأعلى. أي أنه لكل حالة متحمِّسة جديدة، تُضاف عقوبة لأي تداخل بين الحالة التبايُنية الحالية والحالات الذاتية ذات الطاقات الأدنى التي وُجدت بالفعل.

def cost_func_vqd(
parameters, ansatz, prev_states, step, betas, estimator, sampler, hamiltonian
):
estimator_job = estimator.run([(ansatz, hamiltonian, [parameters])])

total_cost = 0

if step > 1:
overlaps = calculate_overlaps(ansatz, prev_states, parameters, sampler)
total_cost = np.sum(
[np.real(betas[state] * overlap) for state, overlap in enumerate(overlaps)]
)

estimator_result = estimator_job.result()[0]

value = estimator_result.data.evs[0] + total_cost

return value

لاحظ بشكل خاص أن دالة التكلفة أعلاه تُشير إلى دالة calculate_overlaps، التي تُنشئ فعليًا دائرة كمية جديدة. إذا أردنا التشغيل على عتاد حقيقي، يجب أيضًا تحويل تلك الدائرة الجديدة بشكل مثلى للتشغيل على الخلفية التي نختارها. لاحظ أن التحويل قد بُني في دالتي calculate_overlaps أو cost_func_vqd. جرِّب تعديل الكود بنفسك لإضافة هذا التحويل الإضافي (والشرطي) — لكن سيتم ذلك من أجلك أيضًا في الدرس التالي.

في هذا الدرس، سنشغِّل خوارزمية VQD باستخدام Statevector Sampler وStatevector Estimator:

from qiskit.primitives import StatevectorEstimator as Estimator

sampler = Sampler()
estimator = Estimator()

سنُدخل متغيّرًا للتقدير. في الدرس التالي سنضيف سياقًا فيزيائيًا لهذا، مثل الحالة المتحمِّسة لجزيء. قد يكون من المفيد التفكير في هذا المتغيّر على أنه هاملتوني لنظام يمكن أن تكون له حالات متحمِّسة، حتى لو لم يُختَر هذا المتغيّر ليتوافق مع أي جزيء أو ذرة معينة.

from qiskit.quantum_info import SparsePauliOp

observable = SparsePauliOp.from_list([("II", 2), ("XX", -2), ("YY", 3), ("ZZ", -3)])

هنا، نحدد العدد الإجمالي للحالات التي نرغب في حسابها (حالة الأساس والحالات المتحمِّسة، k)، والعقوبات (betas) للتداخل بين متجهات الحالات التي يجب أن تكون متعامدة. سيتم استكشاف تداعيات اختيار betas مرتفعة جدًا أو منخفضة جدًا في الدرس التالي. في الوقت الحالي، سنستخدم ببساطة تلك المُقدَّمة أدناه. سنبدأ باستخدام جميع الأصفار كمعاملاتنا. في حساباتك الخاصة، قد ترغب في استخدام معاملات أولية أكثر ذكاءً بناءً على معرفتك بالنظام أو على حسابات سابقة.

k = 3
betas = [33, 33, 33]
x0 = np.zeros(8)

يمكننا الآن تشغيل الحساب:

from scipy.optimize import minimize

prev_states = []
prev_opt_parameters = []
eigenvalues = []

for step in range(1, k + 1):
if step > 1:
prev_states.append(ansatz.assign_parameters(prev_opt_parameters))

result = minimize(
cost_func_vqd,
x0,
args=(ansatz, prev_states, step, betas, estimator, sampler, observable),
method="COBYLA",
options={
"maxiter": 200,
},
)
print(result)

prev_opt_parameters = result.x
eigenvalues.append(result.fun)
message: Optimization terminated successfully.
success: True
status: 1
fun: -5.999999979545955
x: [-5.150e-01 -5.452e-02 -1.571e+00 -2.853e-05 2.671e-01
-2.672e-01 -8.509e-01 -8.510e-01]
nfev: 131
maxcv: 0.0
message: Optimization terminated successfully.
success: True
status: 1
fun: 4.024550284767612
x: [-3.745e-01 1.041e+00 8.637e-01 1.202e+00 -8.847e-02
1.181e-02 7.611e-01 -3.006e-01]
nfev: 110
maxcv: 0.0
message: Optimization terminated successfully.
success: True
status: 1
fun: 5.608925562838559
x: [-2.670e-01 1.280e+00 1.070e+00 -8.031e-01 -1.524e-01
-6.956e-02 7.018e-01 1.514e+00]
nfev: 90
maxcv: 0.0

القيم التي حصلنا عليها من دالة التكلفة هي تقريبًا -6.00 و4.02 و5.61. المهم في هذه النتائج أن قيم الدالة آخذة في الازدياد. لو حصلنا على حالة أولى متحمِّسة ذات طاقة أدنى من حساب الأولي غير المقيَّد لحالة الأساس، كان ذلك سيشير إلى خطأ ما في كودنا.

قيم x هي المعاملات التي أعطت متجه حالة يقابل كل تكلفة (طاقة) من هذه التكاليف.

وأخيرًا، نلاحظ أن جميع التقليلات الثلاثة تقاربت ضمن التسامح الافتراضي للمحسِّن الكلاسيكي (هنا COBYLA). احتاجت إلى 131 و110 و90 تقييمًا للدالة على التوالي.

الانحدار بأخذ العينات الكمية (QSR)

أحد المشاكل الرئيسية في VQE هو النداءات المتعددة لحاسوب كمي المطلوبة للحصول على المعاملات لكل خطوة، مثلًا kk، k1k-1، وهكذا. هذا مُشكل بشكل خاص عندما يكون الوصول إلى أجهزة الكم مُصطَفًا في قائمة انتظار. بينما يمكن استخدام Session لتجميع نداءات تكرارية متعددة، فإن نهجًا بديلًا هو استخدام أخذ العينات. باستخدام موارد كلاسيكية أكثر، يمكننا إتمام عملية التحسين الكاملة في نداء واحد. هنا يأتي دور الانحدار بأخذ العينات الكمية. نظرًا لأن الوصول إلى أجهزة الكم لا يزال سلعة ذات عرض منخفض وطلب مرتفع، نجد هذه المقايضة ممكنة ومناسبة للعديد من الدراسات الحالية. يستغل هذا النهج جميع الإمكانيات الكلاسيكية المتاحة مع الإبقاء على كثير من الآليات الداخلية والخصائص الجوهرية للحسابات الكمية التي لا تظهر في المحاكاة.

مخطط يوضح كيف يستخدم QSR مكوّنات الخوارزمية التبايُنية.

الفكرة وراء QSR هي أن دالة التكلفة C(θ):=ψ(θ)H^ψ(θ)C(\theta) := \langle \psi(\theta) | \hat{H} | \psi(\theta)\rangle يمكن التعبير عنها كمتسلسلة فورييه بالطريقة التالية:

C(θ):=ψ(θ)H^ψ(θ):=a0+k=1S[akcos(kθ)+bksin(kθ)]\begin{aligned} C(\vec{\theta}) & := \langle \psi(\theta) | \hat{H} | \psi(\theta)\rangle \\[1mm] & := a_0 + \sum_{k=1}^S[a_k\cos(k\theta)+ b_k\sin(k\theta)] \\[1mm] \end{aligned}

اعتمادًا على دورية وعرض نطاق الدالة الأصلية، قد تكون المجموعة SS منتهية أو لا نهائية. لأغراض هذا النقاش، سنفترض أنها لا نهائية. الخطوة التالية هي أخذ عينات من دالة التكلفة C(θ)C(\theta) مرات متعددة للحصول على معاملات فورييه {a0,ak,bk}k=1S\{a_0, a_k, b_k\}_{k=1}^S. تحديدًا، بما أن لدينا 2S+12S+1 مجهولًا، سنحتاج إلى أخذ عينات من دالة التكلفة 2S+12S+1 مرة.

إذا أخذنا عينات من دالة التكلفة لـ 2S+12S+1 قيمة معاملة {θ1,...,θ2S+1}\{\theta_1,...,\theta_{2S+1}\}، يمكننا الحصول على النظام التالي:

(1cos(θ1)sin(θ1)cos(2θ1)...sin(Sθ1)1cos(θ2)sin(θ2)cos(2θ2)sin(Sθ2)1cos(θ2S+1)sin(θ2S+1)cos(2θ2S+1)sin(Sθ2S+1))(a0a1b1a2bS)=(C(θ1)C(θ2)C(θ2S+1)),\begin{pmatrix} 1 & \cos(\theta_1) & \sin(\theta_1) & \cos(2\theta_1) & ... & \sin(S\theta_1) \\ 1 & \cos(\theta_2) & \sin(\theta_2) & \cos(2\theta_2) & \cdots & \sin(S\theta_2)\\ \vdots & \vdots & \vdots & \vdots & \ddots & \vdots\\ 1 & \cos(\theta_{2S+1}) & \sin(\theta_{2S+1}) & \cos(2\theta_{2S+1}) & \cdots & \sin(S\theta_{2S+1}) \end{pmatrix} \begin{pmatrix} a_0 \\ a_1 \\ b_1 \\ a_2 \\ \vdots \\ b_S \end{pmatrix} = \begin{pmatrix} C(\theta_1) \\ C(\theta_2) \\ \vdots \\ C(\theta_{2S+1}) \end{pmatrix},

الذي سنُعيد كتابته كـ

Fa=c.Fa=c.

عمليًا، هذا النظام غير متسق عمومًا لأن قيم دالة التكلفة cc ليست دقيقة. لذلك، من الجيد عادةً تطبيعها بضربها بـ FF^\dagger من اليسار، مما ينتج:

FFa=Fc.F^\dagger Fa = F^\dagger c.

هذا النظام الجديد دائمًا متسق، وحله هو حل المربعات الصغرى للمسألة الأصلية. إذا كان لدينا kk معاملة بدلًا من واحدة فقط، وكان لكل معاملة θi\theta^i قيمة SiS_i خاصة بها لـ i1,...,ki \in {1,...,k}، فإن العدد الإجمالي من العينات المطلوبة هو:

T=i=1k(2Si+1)i=1k(2Smax+1)=(2Smax+1)n,T=\prod_{i=1}^k(2S_i+1)\leq \prod_{i=1}^k(2S_{max}+1) = (2S_{max}+1)^n,

حيث Smax=maxi(Si)S_{\max} = \max_i(S_i). علاوةً على ذلك، فإن ضبط SmaxS_{\max} كمعاملة قابلة للضبط (بدلًا من استنتاجها) يفتح إمكانيات جديدة، مثل:

  • المعاينة الزائدة لتحسين الدقة.
  • المعاينة الناقصة لتعزيز الأداء من خلال تقليل تكلفة وقت التشغيل أو التخلص من الحدود الدنيا المحلية.

التصميم النظري

يمكن تلخيص تصميم QSR كما يلي:

  • تحضير مؤثرات مرجعية URU_R.
    • سننتقل من الحالة 0|0\rangle إلى الحالة المرجعية ρ|\rho\rangle
  • تطبيق الشكل التبايُني UV(θi,j)U_V(\vec\theta_{i,j}) لإنشاء الأنزاتز UA(θi,j)U_A(\vec\theta_{i,j}).
    • تحديد عرض النطاق المرتبط بكل معاملة في الأنزاتز. الحد الأعلى كافٍ.
  • التمهيد عند i=0i=0 إذا كان لدينا مسألة مشابهة (تُوجَد عادةً عبر المحاكاة الكلاسيكية أو أخذ العينات).
  • أخذ عينات من دالة التكلفة C(θ):=a0+k=1S[akcos(kθ)+bksin(kθ)]C(\vec\theta) := a_0 + \sum_{k=1}^S[a_k\cos(k\theta)+ b_k\sin(k\theta)] على الأقل TT مرة.
    • T=i=1k(2Si+1)i=1k(2Smax+1)=(2Smax+1)nT=\prod_{i=1}^k(2S_i+1)\leq \prod_{i=1}^k(2S_{max}+1) = (2S_{max}+1)^n
    • تحديد ما إذا كانت المعاينة الزائدة/الناقصة مناسبة لموازنة السرعة مقابل الدقة عن طريق ضبط TT.
  • حساب معاملات فورييه من العينات (أي حل نظام المعادلات الخطي المُطبَّع).
  • حل الحد الأدنى العالمي لدالة الانحدار الناتجة على آلة كلاسيكية.

ملخص

من خلال هذا الدرس، تعلمت عن نماذج تبايُنية متعددة متاحة:

  • التصميم العام
  • إدخال الأوزان والعقوبات لضبط دالة التكلفة
  • استكشاف المعاينة الناقصة مقابل الزائدة للمقايضة بين السرعة والدقة

يمكن تكييف هذه الأفكار لتشكيل خوارزمية تبايُنية مخصصة تتناسب مع مسألتك. نشجعك على مشاركة نتائجك مع المجتمع. سيستكشف الدرس التالي كيفية استخدام خوارزمية تبايُنية لحل تطبيق ما.