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

خوارزمية دوتش

تحل خوارزمية دوتش مسألة التكافؤ في الحالة الخاصة n=1n = 1. في سياق الحوسبة الكمومية تُعرف هذه المسألة أحيانًا بـمسألة دوتش، وسنتبع هذا التسمية في هذا الدرس.

بدقة أكبر، يُمثَّل المدخل بدالة f:ΣΣf:\Sigma \rightarrow \Sigma من بت إلى بت. توجد أربع دوال من هذا النوع:

af1(a)0010af2(a)0011af3(a)0110af4(a)0111\rule[-10mm]{0mm}{10mm} \begin{array}{c|c} a & f_1(a)\\ \hline 0 & 0\\ 1 & 0 \end{array} \qquad \begin{array}{c|c} a & f_2(a)\\ \hline 0 & 0\\ 1 & 1 \end{array} \qquad \begin{array}{c|c} a & f_3(a)\\ \hline 0 & 1\\ 1 & 0 \end{array} \qquad \begin{array}{c|c} a & f_4(a)\\ \hline 0 & 1\\ 1 & 1 \end{array}

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

مسألة دوتش

المدخل: دالة f:{0,1}{0,1}f:\{0,1\}\rightarrow\{0,1\}
المخرج: 00 إذا كانت ff ثابتة، 11 إذا كانت ff متوازنة

إذا نظرنا إلى الدالة المدخلة ff في مسألة دوتش باعتبارها تمثيلًا للوصول العشوائي إلى سلسلة نصية، فنحن نفكر في سلسلة من بتين: f(0)f(1)f(0)f(1).

functionstringf100f201f310f411\begin{array}{cc} \mathsf{function} & \mathsf{string}\\ \hline f_1 & 00 \\ f_2 & 01 \\ f_3 & 10 \\ f_4 & 11 \end{array}

بهذه الطريقة، تصبح مسألة دوتش حساب التكافؤ (أو ما يعادله OR الحصري XOR) للبتين.

كل خوارزمية استعلام كلاسيكية تحل هذه المسألة بشكل صحيح يجب أن تستعلم عن كلا البتين: f(0)f(0) وf(1)f(1). إذا علمنا أن f(1)=1f(1) = 1 مثلًا، فقد تكون الإجابة لا تزال 00 أو 11 اعتمادًا على ما إذا كانت f(0)=1f(0) = 1 أو f(0)=0f(0) = 0 على التوالي. كل حالة أخرى مشابهة؛ معرفة بت واحد فقط من اثنين لا تُقدِّم أي معلومة عن تكافؤهما. لذلك، الدائرة المنطقية الموضحة في القسم السابق هي الأفضل من حيث عدد الاستعلامات اللازمة لحل هذه المسألة.

وصف الدائرة الكمومية

تحل خوارزمية دوتش مسألة دوتش باستخدام استعلام واحد فقط، مما يوفر ميزة قابلة للقياس للحوسبة الكمومية على الكلاسيكية. قد تبدو هذه الميزة متواضعة — استعلام واحد مقابل اثنين — لكن علينا أن نبدأ من مكان ما. التقدم العلمي يبدأ أحيانًا بأصول متواضعة الظاهر.

فيما يلي الدائرة الكمومية التي تصف خوارزمية دوتش:

خوارزمية دوتش

التحليل

لتحليل خوارزمية دوتش، سنتتبع تأثير الدائرة أعلاه ونُحدِّد حالات الكيوبتات في اللحظات التي يقترحها هذا الشكل:

الحالات أثناء تنفيذ خوارزمية دوتش

الحالة الابتدائية هي 10\vert 1\rangle \vert 0 \rangle، وتحوِّل عمليتا هادامار على الجانب الأيسر من الدائرة هذه الحالة إلى

π1=+=12(01)0+12(01)1.\vert \pi_1 \rangle = \vert - \rangle \vert + \rangle = \frac{1}{2} \bigl( \vert 0\rangle - \vert 1\rangle \bigr) \vert 0\rangle + \frac{1}{2} \bigl( \vert 0\rangle - \vert 1\rangle \bigr) \vert 1\rangle.

(كالعادة، نتبع اتفاقية Qiskit لترتيب الكيوبتات التي تضع الكيوبت العلوي على اليمين والكيوبت السفلي على اليسار.) قد يبدو كتابة هذه الحالة المنتجة بهذه الصورة الموزَّعة جزئيًا غير حدسي، لكن هذا سيجعل التعبيرات اللاحقة أكثر إيجازًا.

بعد ذلك، تُنفَّذ بوابة UfU_f. وفقًا لتعريف بوابة UfU_f، تُطبَّق عملية XOR لقيمة الدالة ff للحالة الكلاسيكية للكيوبت العلوي/الأيمن على الكيوبت السفلي/الأيسر، مما يحوِّل π1\vert \pi_1\rangle إلى الحالة

π2=12(0f(0)1f(0))0+12(0f(1)1f(1))1.\vert \pi_2 \rangle = \frac{1}{2} \bigl( \vert 0 \oplus f(0) \rangle - \vert 1 \oplus f(0) \rangle \bigr) \vert 0 \rangle + \frac{1}{2} \bigl( \vert 0 \oplus f(1) \rangle - \vert 1 \oplus f(1) \rangle \bigr) \vert 1 \rangle.

يمكننا تبسيط هذا التعبير بملاحظة أن الصيغة

0a1a=(1)a(01)\vert 0 \oplus a\rangle - \vert 1 \oplus a\rangle = (-1)^a \bigl( \vert 0\rangle - \vert 1\rangle \bigr)

تنطبق على كلتا القيمتين الممكنتين aΣa\in\Sigma. الحالتان بصورة أكثر صراحة هما:

0010=01=(1)0(01)0111=10=(1)1(01)\begin{aligned} \vert 0 \oplus 0\rangle - \vert 1 \oplus 0\rangle & = \vert 0 \rangle - \vert 1 \rangle = (-1)^0 \bigl( \vert 0\rangle - \vert 1\rangle \bigr)\\ \vert 0 \oplus 1\rangle - \vert 1 \oplus 1\rangle & = \vert 1 \rangle - \vert 0\rangle = (-1)^1 \bigl( \vert 0\rangle - \vert 1\rangle \bigr) \end{aligned}

وهكذا يمكننا التعبير عن π2\vert\pi_2\rangle بصيغة بديلة:

π2=12(1)f(0)(01)0+12(1)f(1)(01)1=((1)f(0)0+(1)f(1)12).\begin{aligned} \vert\pi_2\rangle & = \frac{1}{2} (-1)^{f(0)} \bigl( \vert 0 \rangle - \vert 1 \rangle \bigr) \vert 0 \rangle + \frac{1}{2} (-1)^{f(1)} \bigl( \vert 0 \rangle - \vert 1 \rangle \bigr) \vert 1 \rangle \\ & = \vert - \rangle \biggl( \frac{(-1)^{f(0)} \vert 0\rangle + (-1)^{f(1)} \vert 1\rangle}{\sqrt{2}}\biggr). \end{aligned}

حدث شيء مثير للاهتمام! رغم أن تأثير بوابة UfU_f على حالات الأساس القياسية يُبقي الكيوبت العلوي/الأيمن دون تغيير ويطبق XOR لقيمة الدالة على الكيوبت السفلي/الأيسر، نرى هنا أن حالة الكيوبت العلوي/الأيمن قد تغيرت (بصفة عامة) بينما بقيت حالة الكيوبت السفلي/الأيسر على ما هي عليه — وتحديدًا في الحالة \vert - \rangle قبل بوابة UfU_f وبعدها. هذه الظاهرة تُعرف بـانعكاس الطور (phase kickback)، وسنتحدث عنها أكثر قريبًا.

مع تبسيط أخير يتمثل في سحب عامل (1)f(0)(-1)^{f(0)} خارج المجموع، نحصل على هذا التعبير للحالة π2\vert\pi_2\rangle:

π2=(1)f(0)(0+(1)f(0)f(1)12)={(1)f(0)+إذا كان f(0)f(1)=0(1)f(0)إذا كان f(0)f(1)=1.\begin{aligned} \vert\pi_2\rangle & = (-1)^{f(0)} \vert - \rangle \biggl( \frac{\vert 0\rangle + (-1)^{f(0) \oplus f(1)} \vert 1\rangle}{\sqrt{2}}\biggr) \\ & = \begin{cases} (-1)^{f(0)} \vert - \rangle \vert + \rangle & \text{إذا كان $f(0) \oplus f(1) = 0$}\\[1mm] (-1)^{f(0)} \vert - \rangle \vert - \rangle & \text{إذا كان $f(0) \oplus f(1) = 1$}. \end{cases} \end{aligned}

لاحظ أن في هذا التعبير لدينا f(0)f(1)f(0) \oplus f(1) في أس 1-1 بدلًا من f(1)f(0)f(1) - f(0)، وهو ما قد نتوقعه من منظور جبري صرف، لكننا نحصل على النتيجة ذاتها في الحالتين. وذلك لأن قيمة (1)k(-1)^k لأي عدد صحيح kk تعتمد فقط على ما إذا كان kk زوجيًا أم فرديًا.

تطبيق بوابة هادامار الأخيرة على الكيوبت العلوي يُعطينا الحالة

π3={(1)f(0)0إذا كان f(0)f(1)=0(1)f(0)1إذا كان f(0)f(1)=1,\vert \pi_3 \rangle = \begin{cases} (-1)^{f(0)} \vert - \rangle \vert 0 \rangle & \text{إذا كان $f(0) \oplus f(1) = 0$}\\[1mm] (-1)^{f(0)} \vert - \rangle \vert 1 \rangle & \text{إذا كان $f(0) \oplus f(1) = 1$}, \end{cases}

مما يؤدي إلى النتيجة الصحيحة باحتمالية 11 عند قياس الكيوبت الأيمن/العلوي.

ملاحظات إضافية حول انعكاس الطور

قبل المضي قُدُمًا، دعنا ننظر إلى التحليل أعلاه من زاوية مختلفة قليلًا قد تُلقي بعض الضوء على ظاهرة انعكاس الطور.

أولًا، لاحظ أن الصيغة التالية تنطبق على كل اختيار للبتين b,cΣb,c\in\Sigma:

bc=Xcb\vert b \oplus c\rangle = X^c \vert b \rangle

يمكن التحقق من ذلك بفحص القيمتين الممكنتين c=0c = 0 وc=1c = 1:

b0=b=Ib=X0bb1=¬b=Xb=X1b.\begin{aligned} \vert b \oplus 0 \rangle & = \vert b\rangle = \mathbb{I} \vert b \rangle = X^0 \vert b \rangle\\ \vert b \oplus 1 \rangle & = \vert \neg b\rangle = X \vert b \rangle = X^1 \vert b \rangle. \end{aligned}

باستخدام هذه الصيغة نرى أن

Uf(ba)=bf(a)a=(Xf(a)b)aU_f \bigl(\vert b\rangle \vert a \rangle\bigr) = \vert b \oplus f(a) \rangle \vert a \rangle = \bigl(X^{f(a)}\vert b \rangle\bigr) \vert a \rangle

لكل اختيار للبتين a,bΣa,b\in\Sigma. لأن هذه الصيغة صحيحة من أجل b=0b=0 وb=1b=1، نرى بالخطية أن

Uf(ψa)=(Xf(a)ψ)aU_f \bigl( \vert \psi \rangle \vert a \rangle \bigr) = \bigl(X^{f(a)}\vert \psi \rangle\bigr) \vert a \rangle

لجميع متجهات الحالة الكمومية ψ\vert \psi\rangle، وبالتالي

Uf(a)=(Xf(a))a=(1)f(a)a.U_f \bigl( \vert - \rangle \vert a \rangle \bigr) = \bigl(X^{f(a)} \vert - \rangle \bigr) \vert a \rangle = (-1)^{f(a)} \vert - \rangle \vert a \rangle.

المفتاح الذي يُجعل هذا ممكنًا هو أن X=X\vert - \rangle = - \vert - \rangle. بالمصطلحات الرياضية، المتجه \vert - \rangle هو متجه ذاتي للمصفوفة XX بـقيمة ذاتية 1-1.

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

مع الأخذ بعين الاعتبار أن الكميات القياسية تتحرك بحرية عبر الجداء التنسوري، نجد طريقة بديلة للاستدلال على كيفية تحويل العملية UfU_f للحالة π1\vert \pi_1\rangle إلى π2\vert \pi_2\rangle في التحليل أعلاه:

π2=Uf(+)=12Uf(0)+12Uf(1)=((1)f(0)0+(1)f(1)12).\begin{aligned} \vert \pi_2 \rangle & = U_f \bigl( \vert - \rangle \vert + \rangle \bigr)\\ & = \frac{1}{\sqrt{2}} U_f \bigl(\vert - \rangle \vert 0\rangle \bigr) + \frac{1}{\sqrt{2}} U_f \bigl(\vert - \rangle \vert 1\rangle \bigr)\\ & = \vert - \rangle \biggl( \frac{(-1)^{f(0)} \vert 0\rangle + (-1)^{f(1)} \vert 1\rangle}{\sqrt{2}}\biggr). \end{aligned}

التطبيق في Qiskit

لنرَ الآن كيف يمكننا تطبيق خوارزمية دوتش في Qiskit. سنبدأ بفحص الإصدار ثم نُجري الاستيرادات اللازمة لهذا التطبيق تحديدًا. في تطبيقات الخوارزميات الأخرى التي ستلي، سنُجري الاستيرادات اللازمة بصورة منفصلة لمزيد من الوحدودية.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit import __version__

print(__version__)
2.1.1
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

أولًا، سنعرِّف دائرة كمومية تُطبِّق بوابة استعلام لإحدى الدوال الأربع f1,f_1, f2,f_2, f3,f_3, أو f4f_4 من بت إلى بت كما وردت سابقًا. كما أشرنا، تطبيق بوابات الاستعلام ليس جزءًا أصيلًا من خوارزمية دوتش في حد ذاتها؛ هنا نُظهر في الأساس إحدى طرق إعداد المدخل على هيئة دائرة كمومية لبوابة الاستعلام.

def deutsch_function(case: int):
# This function generates a quantum circuit for one of the 4 functions
# from one bit to one bit

if case not in [1, 2, 3, 4]:
raise ValueError("`case` must be 1, 2, 3, or 4.")

f = QuantumCircuit(2)
if case in [2, 3]:
f.cx(0, 1)
if case in [3, 4]:
f.x(1)
return f

يمكننا رؤية شكل كل دائرة باستخدام طريقة draw. هذه هي الدائرة للدالة f3f_3.

display(deutsch_function(3).draw(output="mpl"))

Output of the previous code cell

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

def compile_circuit(function: QuantumCircuit):
# Compiles a circuit for use in Deutsch's algorithm.

n = function.num_qubits - 1
qc = QuantumCircuit(n + 1, n)

qc.x(n)
qc.h(range(n + 1))

qc.barrier()
qc.compose(function, inplace=True)
qc.barrier()

qc.h(range(n))
qc.measure(range(n), range(n))

return qc

مجددًا يمكننا رؤية شكل الدائرة باستخدام طريقة draw.

display(compile_circuit(deutsch_function(3)).draw(output="mpl"))

Output of the previous code cell

أخيرًا، سننشئ دالة تُشغِّل الدائرة المعرَّفة مسبقًا مرة واحدة وتُخرج النتيجة المناسبة: "constant" (ثابتة) أو "balanced" (متوازنة).

def deutsch_algorithm(function: QuantumCircuit):
# Determine if a one-bit function is constant or balanced.

qc = compile_circuit(function)

result = AerSimulator().run(qc, shots=1, memory=True).result()
measurements = result.get_memory()
if measurements[0] == "0":
return "constant"
return "balanced"

يمكننا الآن تشغيل خوارزمية دوتش على أي من الدوال الأربع المعرَّفة أعلاه.

f = deutsch_function(3)
display(deutsch_algorithm(f))
'balanced'