محتوای آموزشی

کدنویسی کوانتومی، مقدمه‌ای بر Cirq (بخش دوم)

کدنویسی کوانتومی Cirq

مقدمه‌ای بر cirq

Cirq یک کتابخانه در پایتون است که برای کدنویسی، به کار گیری و بهینه سازی مدارهای کوانتومی و اجرای آنها بر روی رایانه‌های کوانتومی و شبیه‌سازهای کوانتومی توسعه داده شده است. Cirq انتزاعات مفیدی را برای مقابله با رایانه‌های کوانتومی نوفه‌دار در مقیاس رایانه‌های کوانتومیِ متوسطِ امروزی ارائه می‌دهد، جایی که جزئیات سخت افزار برای دستیابی به نتایج پیشرفته حیاتی است. در این مقاله با مباحث پایه‌ای کد نویسی در Cirq، ساخت مدار و ممان‌ها آشنا می‌شویم.

در‌مطلب قبل (مقدمه‌ای بر  Cirq، بخش اول) موارد زیر را آموختیم:

– نصب Cirq

– ساخت کیوبیت

کد های:

  • ساخت NamedQubit ها
  • ساخت LineQubit ها
  • ساخت مدار و اضافه کردن operation ها به مدار
  • اعمال کردن گذرگاه های X, H, Y, Z, CNOT, I

ساخت مدار

در این قسمت از مقدمه‌ای بر Cirq، میخواهیم مدار زیر را بسازیم. در فرایند ساخت، یک موضوع جدید نیز یاد خواهیم گرفت:

مدار cirq

بیایید شروع کنیم.

در ابتدا باید Cirq را import کنیم:

import cirq

حالا می‌خواهیم ۶ کیوبیت بسازیم. آرایه‌ای کیوبیت‌ها در آن قرار دارند را ‍q نامگذاری می‌کنیم.

q = cirq.LineQubit.range(6)

حالا بیایید یک مدار بسازیم و نامِ آن را circuit بگذاریم.

()circuit = cirq.Circuit

حالا باید گذرگاه H را بر روی همه‌ی کیوبیت‌ها اعمال کنیم. (ما در قسمت اول یاد گرفتیم که با استفاده از on_each.  این کار را انجام دهیم.) بیایید این کار را انجام دهیم و ببینیم چه می‌شود.

circuit.append(cirq.H.on_each(q))

print(circuit)

خروجی بدین شکل خواهد بود:

0: ───H───
1: ───H───
2: ───H───
3: ───H───
4: ───H───
5: ───H───

اگر داخل شکل نگاه کنیم، q[5] در ابتدا روی حالت |1〉 است و نه روی حالت |0〉. پس لازم است قبل از اینکه گذرگاه‌های H را اعمال کنیم، اول یک گذرگاه X  روی q[5] اعمال کنیم، و بعد از آن برویم سراغ گذرگاه‌های H. یک مدار جدید می‌سازیم و اینکار را میکنیم.


circuit = cirq.Circuit()
# apply X gate on q[5]
circuit.append(cirq.X(q[5]))
# apply H gate on all qubits.
circuit.append(cirq.H.on_each(q))

بیایید مدار را چاپ کنیم:

print(circuit)

خروجی بدین شکل خواهد بود:

0: ───H───────
1: ───H───────
2: ───H───────
3: ───H───────
4: ───H───────
5: ───X───H───

همانطور که می‌بینید، گذرگاه‌های H ای که روی q[0], q[1], …, q[4] اعمال شده اند، در ستون اول هستند، ولی گذرگاه H ای که روی q[5] اعمال شده، در ستون دوم است. اگر بخواهیم کاری کنیم که مانند عکس، تمامیِ ۶ گذرگاه H در ستون دوم باشند باید چه کنیم؟ اینجاست که باید در مورد Moments یا ممان‌ها صحبت کنیم:

ممان‌ها

ممان‌ها

 

ممان ها مجموعه ای از عملیات ها هستند که همگی در یک زمان انجام میشود. این عملیات ها ممکن است روی کیوبیت‌های مختلف صورت گیرند، اما نکته اصلی در موردِ ممان‌ها رخ‌دادنِ تمامیِ این عملیات‌ها در یک زمان است.

هر ستون داخل مدار ما یک ممان است. همانطور که در تصویر بالا مشاهده می‌کنید:

نکته: cirq.H یک گذرگاه است.

نکته: cirq.H(b) یک عملیات است. (فرض کنید که b یک کیوبیت است.)

نکته: cirq.Moment(cirq.CNOT(b, c)) یک ممان است. (فرض کنید b و c کیوبیت هستند.)

و هر موقع که یک ممان به مدار اضافه می‌شود، اگر در آن بعضی از کیوبیت‌ها، فضای خالی داشته باشند، فضای خالی‌شان بعدا مورد استفاده قرار نمی‌گیرد. احتمالا یک مثال به فهم بهتر کمک خواهد کرد.

مثالِ استفاده از ممان‌ها

این روشی است که ما از یک ممان استفاده میکنیم.

qubits_array = cirq.LineQubit.range(4)
# create a moment which contains one operation
my_moment = cirq.Moment(cirq.H(qubits_array[1]))
# create a moment which contains more than one operations.
my_moment2 = cirq.Moment([
                        cirq.Y(qubits_array[2]),
                        cirq.Y(qubits_array[3]),
                        cirq.Z(qubits_array[0])
                        ])
circuit = cirq.Circuit()
circuit.append([my_moment, my_moment2])
print(circuit)

خروجی بدین شکل خواهد بود:

0: ───────Z───
1: ───X───────
2: ───────Y───
3: ───────Y───

اگر از ممان‌ها استفاده نمی‌کردیم، خروجی بدین شکل می‌شد:

0: ───Z───
1: ───X───
2: ───Y───
3: ───Y───

پس در مثال اولی که داشتیم، (همان مثالی که می‌خواستیم اول X را روی کیوبیتِ ششم اعمال کنیم و بعد روی همه‌ی کیوبیت‌ها، H اعمال کنیم) باید این کارها را انجام دهیم

  • یک ممان بسازیم که شاملِ X(q[5]) باشد.
  • سپس ممان را به مدار اضافه کنیم.

بعد در نهایت میتوانیم آن شش گذرگاه H را اضافه کنیم.

ادامه‌ی ساخت مدار

حالا که می‌دانیم ممان چیست، به ادامه‌ی ساخت مدارمان بپردازیم.(برای ۶ گذرگاه H می‌توانیم ممان بسازیم، می‌توانیم هم نسازیم. نیازی به ساختن نیست. اما ما اینجا به جهت تمرین این کار را انجام می‌دهیم)

 

circuit = cirq.Circuit()
# create a moment called my_moment, in such a way that my_moment contains cirq.X(q[5])
my_moment = cirq.Moment(cirq.X(q[5]))
# and add the my_moment to the circuit.
circuit.append(my_moment)
# create a moment named my_moment2. The my_moment2 contains al
my_moment2 = cirq.Moment(cirq.H.on_each(q))
# add the my_moment2 to the circuit
circuit.append(my_moment2)
print(circuit)

 

خروجی بدین شکل خواهد بود:

0: ───────H───
1: ───────H───
2: ───────H───
3: ───────H───
4: ───────H───
5: ───X───H───

همانطور که میبیند، تمامی گذرگاه‌های H در یک ستون قرار دارند.

کد بالا را می‌توان راحت‌تر پیاده‌سازی کرد. در ادامه این تمرین را آموزش می‌دهیم:

circuit = cirq.Circuit()
# creation of a moment, in such a way the it contains cirq.X(q[5]), and append the moment to the circuit, all in one.
circuit.append(cirq.Moment(cirq.X(q[5])))
# creation of a moment, in such a way the it contains cirq.H.on_each(q) and append the moment to the circuit, all in one.
circuit.append(cirq.Moment(cirq.H.on_each(q)))
print(circuit)

این دو قطعه که دقیقا یک کار را انجام میدهند. خروجی:

0: ───────H───
1: ───────H───
2: ───────H───
3: ───────H───
4: ───────H───
5: ───X───H───

به ساخت مدار ادامه می‌دهیم. الان باید ۳ عدد CNOT اعمال کنیم. سپس روی تمامی کیوبیت‌ها، یک گذرگاه H اعمال کنیم. مواقعی که می‌خواهیم بیشتر از یک عملیات اضافه کردن به مدار را انجام دهیم، می‌توانیم بدین شکل عمل کنیم:

circuit.append([
    cirq.CNOT(q[4], q[5]),
    cirq.CNOT(q[1], q[5]),
    cirq.CNOT(q[0], q[5]),
    cirq.Moment(cirq.H.on_each(q))
])
print(circuit)

خروجی بدین شکل خواهد بود:

0: ───────H───────────@───H───
                      │
1: ───────H───────@───┼───H───
                  │   │
2: ───────H───────┼───┼───H───
                  │   │
3: ───────H───────┼───┼───H───
                  │   │
4: ───────H───@───┼───┼───H───
              │   │   │
5: ───X───H───X───X───X───H───

توجه کنیم که این قطعه، قبلا به مدار اضافه شده بوده است.

0: ───────H───
1: ───────H───
2: ───────H───
3: ───────H───
4: ───────H───
5: ───X───H───

جمع‌بندی

در این محتوای آموزشی مدار زیر پیاده شد و کد اجرا شده و خروجی آن به صورت زیر می‌باشد:

مدار cirq

import cirq
q = cirq.LineQubit.range(6)
circuit = cirq.Circuit()
circuit.append(cirq.Moment(cirq.X(q[5])))
circuit.append(cirq.Moment(cirq.H.on_each(q)))
circuit.append([
    cirq.CNOT(q[4], q[5]),
    cirq.CNOT(q[1], q[5]),
    cirq.CNOT(q[0], q[5]),
    cirq.Moment(cirq.H.on_each(q))
])
print(circuit)

و خروجی به اینصورت خواهد بود:

 

0: ───────H───────────@───H───
                      │
1: ───────H───────@───┼───H───
                  │   │
2: ───────H───────┼───┼───H───
                  │   │
3: ───────H───────┼───┼───H───
                  │   │
4: ───────H───@───┼───┼───H───
              │   │   │
5: ───X───H───X───X───X───H───

در قسمت بعد در مورد شبیه‌سازی مدارها صحبت خواهیم کرد.

لینک مفید:

https://quantumai.google/cirq/build/circuits