الگوریتم شورتوسط پیتر شور در یک مقالهی مهم [1] در سال 1995 به عنوان الگوریتمی برای فاکتورگیری اعداد بزرگ با استفاده از محاسبات کوانتومی پیشنهاد شد. در سال 2025، یعنی 30 سال بعد، پردازندههای کوانتومی اولیه تولید و در دسترس عموم قرار میگیرند و آزمایش واقعی الگوریتم را ممکن میسازند. آیا میتوانیم الگوریتم شور را با موفقیت روی اعداد بزرگ اجرا کنیم؟ پاسخ کاملاً مشخص است که خیر، زیرا این امر به پردازندههای کوانتومی با هزاران کیوبیت و نویز کوانتومی بسیار کم نیاز دارد و ما هنوز به آنجا نرسیدهایم. اما در مورد اعداد کوچک چطور؟ و ضمناً، چگونه الگوریتم شور را به طور ملموس پیادهسازی کنیم؟
در این پست، ما راهنمایی برای پیادهسازی الگوریتم شور ارائه میدهیم، با تأکید ویژه بر تحقق مدار کوانتومی یافتن ترتیب و محاسبات حسابی مدولار که در هسته الگوریتم قرار دارند. ما یک مخزن گیت را با پیادهسازی کامل در Qiskit پیوند میدهیم. در نهایت، ما برخی شبیهسازیها را اجرا میکنیم و نتایج محاسبات واقعی را روی سختافزار کوانتومی IBM، از سال ۲۰۲۵، ارائه میدهیم.
برای دنبال کردن این پست، ایدهآل است که با برخی از اصول اولیه محاسبات کوانتومی، یعنی دستکاری کیوبیتها و عملیات استاندارد گیتهای واحد، و کمی جبر خطی آشنا باشید.
سلب مسئولیت ۱: اگرچه هدف من رسیدن به سطح علمی دقیقی از دقت است، اما این یک مقاله دانشگاهی نیست و من وانمود نمیکنم که در این زمینه متخصص هستم.
سلب مسئولیت ۲: هیچ گونه هوش مصنوعی برای تولید این پست استفاده نشده است.
الگوریتمی نوآورانه برای فاکتورگیری اعداد
الگوریتم شور الگوریتمی است که هدف آن یافتن یک عامل غیربدیهی از یک عدد صحیح N است. اگرچه یافتن عاملی برای یک N به اندازه کافی کوچک، مثلاً با امتحان کردن مقادیر ممکن تا N ½، آسان است، اما وقتی N واقعاً بزرگ باشد، مانند N ~ 2 1000 ، این مسئله غیرعملی میشود، زیرا فضای جستجو خیلی بزرگ میشود. عمر یک انسان برای یافتن عاملی از چنین عدد صحیح بزرگی با استفاده از یک کامپیوتر کلاسیک کافی نخواهد بود.
اگر تعداد ارقام برای نوشتن N را به صورت دودویی با n = ⌈log₂(N)⌉ نشان دهیم، بهترین الگوریتم کلاسیک شناخته شده برای مقداری ثابت c، پیچیدگی زمانی exp(cn 1/3 (log₂n) 2/3 ) دارد، یعنی پیچیدگی زمانی نمایی . منظور از الگوریتم «کلاسیک» الگوریتمی است که میتواند روی یک کامپیوتر سنتی اجرا شود، یعنی الگوریتمی که از عملیات حسابی روی اعداد ساخته شده است. این اساساً همه الگوریتمها را شامل میشود، به جز الگوریتمهای کوانتومی .
الگوریتم شور یک الگوریتم کوانتومی است ، به این معنی که شامل عملیات روی یک سیستم کوانتومی، در این مورد روی کیوبیتها، میشود. علاوه بر این، یک الگوریتم احتمالی است، به این معنی که تضمین میشود با احتمال بالا کار کند، اما گاهی اوقات میتواند شکست بخورد.
الگوریتم شور قادر است ضریبی از N را در پیچیدگی زمانی O(n^ 2 log n) با احتمال بالا، در کارآمدترین پیادهسازی خود، یعنی در پیچیدگی زمانی چندجملهای ، پیدا کند . این احتمالاً چشمگیرترین نمونه از یک الگوریتم کوانتومی است که تاکنون الگوریتمهای کلاسیک را شکست داده است.
علاوه بر این، اتفاقاً مسئله تجزیه اعداد صحیح بزرگ، در قلب رمزنگاری کلید عمومی و الگوریتم RSA قرار دارد که امروزه به طور گسترده برای ایمنسازی ارتباطات اینترنتی استفاده میشود. الگوریتم شور، اگر با موفقیت روی یک کامپیوتر کوانتومی با چند هزار کیوبیت اجرا شود، میتواند این طرح رمزگذاری را بشکند. این امر آن را به یکی از محبوبترین کاربردها در محاسبات کوانتومی تبدیل میکند.
اگرچه ما هنوز تا حدودی از داشتن یک کامپیوتر کوانتومی با ظرفیت اجرای الگوریتم شور روی اعداد بزرگ فاصله داریم، اما پیشرفتهای فعلی امکان آزمایش آن را روی اعداد کوچک فراهم میکند. بنابراین زمان آن رسیده است که نگاه عمیقتری به الگوریتم شور بیندازیم، ببینیم چگونه کار میکند، چگونه میتوانیم آن را پیادهسازی و روی سختافزار کوانتومی اجرا کنیم.
با بهرهگیری از پلتفرم کوانتومی IBM که امکان دسترسی آزاد محدودی به پردازندههای کوانتومی واقعی (QPU) را فراهم میکند، من الگوریتم کامل را با Qiskit SDK پیادهسازی کرده و آن را روی تعداد کمی آزمایش کردهام. پیادهسازی کامل در این مخزن qiskit-shor موجود است .
حالا بیایید به الگوریتم بپردازیم.
الگوریتم
مقدمههایی برای الگوریتم شور در وب بسیار زیاد است (مثلاً به ویکیپدیا مراجعه کنید ). ما فقط خود الگوریتم را مینویسیم و ایدههای مربوط به آن را توضیح میدهیم، اما توضیح نمیدهیم که چرا کار میکند و اثباتی برای هر گزاره ارائه نمیدهیم .
یک عدد صحیح مرکب N را در نظر بگیرید، یعنی عددی که عوامل اول غیر بدیهی را میپذیرد. همچنین لازم است که N فرد باشد و توانی از یک عدد اول نباشد (در این موارد، میتوانیم به راحتی یک عامل غیر بدیهی پیدا کنیم).
سپس، مراحل الگوریتم عبارتند از:
- یک عدد صحیح تصادفی 1 < A < N انتخاب کنید و gcd(A, N) را محاسبه کنید. اگر gcd(A, N) > 1 باشد، آنگاه gcd(A, N) یک عامل غیر بدیهی از N است و کار تمام است (حالت خوش شانس). در غیر این صورت A و N نسبت به هم اول هستند (حالت معمول).
- مرتبه A در ZN را بیابید ، یعنی کوچکترین عدد صحیح 1 < r < N به طوری که Ar r = 1 mod N باشد، با استفاده از الگوریتم کوانتومی تخمین فاز (به زیر مراجعه کنید).
- اگر r فرد باشد، به مرحله ۱ برگردید و A دیگری را انتخاب کنید. در غیر این صورت، d = gcd(A r/2 − 1, N) را محاسبه کنید. اگر d > 1 باشد، آنگاه d یک عامل غیربدیهی از N است. در غیر این صورت، دوباره از مرحله ۱ شروع کنید.
پیتر شور این الگوریتم را در یک مقالهی مهم [1] پیشنهاد داد و ثابت کرد که این الگوریتم با احتمال بالا، ضریبی از N را در زمان چندجملهای پیدا میکند.
در میان مراحل ذکر شده در بالا، تنها مرحله یافتن ترتیب نیاز به یک عملیات کوانتومی دارد. مراحل دیگر، عملیات کلاسیک هستند که به راحتی روی یک کامپیوتر کلاسیک انجام میشوند.
الگوریتم کوانتومی شامل اعمال عملیات واحد روی مجموعهای از کیوبیتها است که اعداد را در نمادگذاری دودویی نشان میدهند. عدد صحیح
\[ x = \sum_{i=0}^{m-1} x_i 2^i, \quad x_i \in \{0,1\} \,,\]
با حالت m-qubit نشان داده میشود
\[ |x\rangle = |x_0\rangle |x_1\rangle …|x_{m-1}\rangle \]
برای مثال، عدد ۱۳ = ۲۰ +۲۲ + ۲۳ که با «عدد صحیح کوانتومی» (حالت ۴ کیوبیتی) نمایش داده میشود |۱۳⟩ = |۱⟩|۰⟩|۱⟩|۱⟩ .
برای یافتن مرتبه r عدد صحیح A در ZN ، ایده الگوریتم شور این است که از این واقعیت استفاده کند که عملگر واحد
\[ U_A : x \rightarrow Ax \,\, \text{mod} \,\, N \]
مقادیر ویژه به شکل exp (2π i j/r) را میپذیرد، که در آن 0 ≤ j < r است، و بردار |1⟩ (“عدد صحیح کوانتومی 1”) را میتوان به صورت ترکیبی خطی از بردارهای ویژه مربوطه بیان کرد. این الگوریتم سعی میکند حداقل یکی از کسرهای j/r را تخمین بزند. به این عمل تخمین فاز میگویند ، زیرا ما فاز Φ = 2π j /r یک مقدار ویژه exp(iΦ) از عملگر U A را تخمین میزنیم .
ما مدار کوانتومی واقعی را که باید در بخش بعدی اجرا شود، ارائه خواهیم داد. الگوریتم کوانتومی شامل اجرای این مدار و اندازهگیری m بیت خروجی آن و تشکیل عدد k در نماد دودویی است. این عدد k به گونهای است که k/2m باید برای 0 ≤ j < r با احتمال بالا به j/r نزدیک باشد. مگر اینکه در حالت بدشانسی (مانند j=0) قرار بگیریم، میتوانیم مقدار r را با پیدا کردن کسری از فرم a/b، که b < N، نزدیکترین به k/2m است و شناسایی r=b (کتابخانههایی وجود دارند که این کار را به طور موثر انجام میدهند) استخراج کنیم. به طور معمول، میتوان مدار یافتن ترتیب را اجرا کرد و نتایج آن را بارها اندازهگیری کرد تا r را با احتمال بسیار زیاد پیدا کرد. انتظار میرود که توزیع خروجیهای k/2m برای 0 ≤ j < r در تمام مقادیر j/r دارای پیک (با بزرگی یکسان) باشد.
پیادهسازی تمام عملیات کلاسیک آسان است و میتوان آنها را در زمان لگاریتم N اجرا کرد، بنابراین ما فقط باید نگران پیادهسازی و اجرای مدار کوانتومیِ یابندهی ترتیب باشیم. بیایید ببینیم چگونه به نظر میرسد.
مدار کوانتومی یابنده نظم
مدار یافتن ترتیب در شکل زیر نشان داده شده است. میتوان چندین تغییر در مدار ایجاد کرد تا کارایی آن بهبود یابد، اما اجازه دهید این بحث را به بعد موکول کنیم.
دو گروه از کیوبیتها وجود دارد: یک گروه از n کیوبیت که با حالت عدد صحیح کوانتومی |1⟩، یعنی |x⟩ با x=1 مقداردهی اولیه شدهاند، که کیوبیتهای هدف نامیده میشوند (کیوبیتهای پایینتر در شکل)، و گروه دیگری از 2n کیوبیت، که کیوبیتهای کنترل نامیده میشوند (کیوبیتهای بالاتر در شکل). کیوبیتهای کنترل با استفاده از گیتهای هادامارد، با برهمنهی همه حالتهای عدد صحیح مقداردهی اولیه میشوند،
\[ (H|0\rangle)^{\otimes 2n} = \left( \frac{|0\rangle + |1\rangle}{\sqrt 2}\right)^{\otimes 2n} = \frac{1}{2^n} \sum_{x =0}^{2^{2n}-1} |x\rangle \]
و سپس به عنوان کیوبیتهای کنترل برای عملیات واحد U D که به صورت متوالی روی کیوبیتهای هدف عمل میکنند، استفاده میشوند.
\[
CU_{D}|b\rangle|x\rangle = \left\{
\begin{align}
& |0\rangle \, |x\rangle & \text{if $b = 0$} \\
& |1\rangle \, |Dx\, \text{mod}\, N\rangle & \text{if $b = 1$}
\end{align}
\right.
\,,
\]
با در نظر گرفتن مقادیر D
\[ D = A^{2^i} \, \text{mod} \, N \,, \quad i = 0, …, 2n-1, \]
در نهایت، کیوبیتهای کنترل توسط یک گیت QFT معکوس تبدیل شده و همگی اندازهگیری میشوند (که در شکل با دایرههایی با حرف «m» نشان داده شدهاند).
میتوان تعداد کیوبیتهای کنترلی 2n را با تعداد دیگری از کیوبیتهای کنترلی m جایگزین کرد. هرچه کیوبیتهای کنترلی بیشتر باشند، فاز تخمینی k/2m از عملگر U A بهتر خواهد بود . انتخاب m=2n مصالحهای بین دقت و اندازه مدار است.
اینکه چرا این مدار تخمین فاز را انجام میدهد، موضوع بسیاری از مباحث مقدماتی الگوریتم شور است. سخنرانی IBM جای بسیار خوبی برای مطالعه این موضوع است.
در مدار فوق، همه اجزا به راحتی در Qiskit SDK پیادهسازی میشوند، به جز عملگر واحد U A (و نسخه کنترلشده آن CU A ). اینجاست که تمام مشکل وجود دارد. اکثر تحقیقات دانشگاهی در مورد الگوریتم شور حول بهینهسازی پیادهسازی U A میچرخد . تصویر بالا از مدار یافتن ترتیب نشان میدهد که 3n کیوبیت برای پیادهسازی الگوریتم کوانتومی کافی است، اما خود گیت U A در واقع به n + c کیوبیت اضافی نیاز دارد که به آنها ancilla ry یا ancilla qubits گفته میشود (ثابت دقیق c به پیادهسازی انتخاب شده بستگی دارد).
قبل از بحث در مورد پیادهسازی مداری UA ، اجازه دهید اشاره کنیم که یک سادهسازی مهم در مدار فوق وجود دارد. 2n کیوبیت کنترل را میتوان با یک کیوبیت واحد (!) جایگزین کرد که تحت یک سری اقدامات گیت واحد، اندازهگیریها و تنظیم مجدد قرار میگیرد و منجر به کاهش زیادی در تعداد کیوبیتهای مورد نیاز برای اجرای الگوریتم شور میشود، اما به قیمت معرفی عملیات جریان کنترل، یعنی اقدامات گیت بسته به اندازهگیریهای میانی. اگرچه این ممکن است در تئوری به عنوان یک هزینه ارزان به نظر برسد، اما در عمل، مدیریت گیتهای جریان کنترل از نظر عملیاتی پیچیدهتر از عملیات واحد استاندارد است. مدار “یک کیوبیت کنترل” در شکل زیر نشان داده شده است.
که در آن m i ∈ {0, 1} مقادیر اندازهگیری متوالی کیوبیت کنترل منحصر به فرد هستند و X m گیت X (= گیت NOT) است اگر m=1، یا گیت هویت اگر m=0 باشد. اعمال X m کیوبیت کنترل را به |0⟩ بازنشانی میکند. R i گیتهای فاز (= گیتهای چرخش RZ) با پارامترهای فاز بسته به تمام مقادیر اندازهگیری قبلی هستند. جزئیات و توضیحات این سادهسازی را میتوان، به عنوان مثال، در [3] یافت.
گیت U A و محاسبات مدولار کوانتومی
توجه: این بخش فنیتر است. برخی از خوانندگان ممکن است بخواهند در اولین خوانش از این بخش صرف نظر کنند و مستقیماً به بخش بعدی بروند.
حال بیایید روی مداری که عمل واحد را اجرا میکند تمرکز کنیم.
\[ U_A : x \rightarrow Ax \,\, \text{mod} \,\, N \]
خوانندهی تیزبین ممکن است بپرسد که آیا این واقعاً یک عملیات واحد است، زیرا این عملیات به دلیل عملیات پیمانهای N خیلی دوطرفه به نظر نمیرسد. این نکتهی بسیار مهمی است، زیرا با استفاده از گیتهای واحد، ما فقط میتوانیم عملیات واحد را پیادهسازی کنیم. واقعیت این است که U A که بر روی فضای اعداد صحیح در [0, N] عمل میکند، یک تابع دوطرفه است، اگر و تنها اگر A و N اعداد صحیح هماول باشند، که برای مقادیر در نظر گرفته شده در الگوریتم شور صادق است. عملیات معکوس U B است ، که B معکوس A در Z N است، یعنی B یک عدد صحیح است به طوری که BA = 1 mod N. این واقعیت که A و N هماول هستند، وجود B را تضمین میکند.
بنابراین از لحاظ تئوری میتوان یک عملگر واحد U A ساخت که روی فضای S که توسط بردارهای |x⟩ پوشش داده شده است، با 0 ≤ x < N عمل کند. در مدار یافتن ترتیب، دنبالهای از عملیات U D (کنترلشده) ، با مقادیر مختلف D، به حالت اولیه |1⟩ که در S است، اعمال میشوند. عمل U A روی حالتهای |x⟩، با x ≥ N، مهم نیست، زیرا این حالت رخ نخواهد داد. میتوانیم نحوه عملکرد مدار گیت U A خود را روی آن حالتهای عدد صحیح بزرگتر نادیده بگیریم .
برای اینکه ارائه به اندازه کافی کوتاه باشد، ما فقط مهمترین ویژگیهای پیادهسازی UA را ارائه خواهیم داد و برخی از نکات مربوط به مقالات مرتبط را برای خواننده علاقهمند باقی میگذاریم.
بلوک سازنده مهمی که باید پیادهسازی شود، افزودن ماژولار است:
\[ \text{add}(Y,N): \quad |x\rangle \rightarrow |(x+Y) \, \text{mod} \, N \rangle \]
با 0 ≤ Y < N یک عدد صحیح «کلاسیک»، یعنی یک پارامتر داده شده، و 0 ≤ x < N یک عدد صحیح «کوانتومی»، یعنی یک عدد صحیح که توسط حالت کوانتومی |x⟩ نمایش داده میشود، همانطور که در بخشهای قبلی توضیح داده شد. برای پیادهسازی این عملیات، حداقل به n = ⌈log 2 (N)⌉ کیوبیت برای نمایش اعداد صحیح کوانتومی به پیمانه N نیاز داریم، بنابراین فرض میکنیم که n اندازه رجیستر کوانتومی است که با آن کار میکنیم، یعنی تعداد کیوبیتهایی که x را در خود جای دادهاند. این بدان معناست که میتوانیم اعداد صحیح کوانتومی بین 0 و 2 را به صورت n -1 نمایش دهیم.
دو «مکتب فکری» برای پیادهسازی این عملیات وجود دارد. رویکرد «کلیفورد+تی» فقط از گیتهای NOT، H، S، S -1 ، CNOT و Toffoli استفاده میکند، در حالی که رویکرد «تبدیل فوریه کوانتومی» (QFT) جمع را از طریق گیتهای فاز پارامتری P(λ) روی نمایش فضای فوریه عدد صحیح ورودی انجام میدهد (در ادامه بیشتر در این مورد صحبت خواهیم کرد).
رویکرد کلیفورد+تی اساساً از یک روش نسبتاً سرراست «مدرسهای» استفاده میکند، که بیتهای دو عدد کوانتومی را که به صورت دودویی نوشته شدهاند، جمع میکند و واحدهای انتقال را در کیوبیتهای آنسیلا پیگیری میکند. در پیادهسازی [6]، کل روش به حدود 10n گیت و یک کیوبیت آنسیلا نیاز دارد و عمق آن تقریباً 2n است (این مفاهیم در بخش پیچیدگی الگوریتم در زیر مورد بحث قرار گرفتهاند). این رویکرد را میتوان با جمع یک عدد کلاسیک و یک عدد کوانتومی تطبیق داد.
رویکرد QFT در کار Draper [4] پیشنهاد شد. این رویکرد با اعمال یک گیت QFT بر روی |x⟩ که از گیتهای H و P(π/2 j ) تشکیل شده است، آغاز میشود و یک برهمنهی از حالتها ایجاد میکند.
\[ QFT|x\rangle = \frac{1}{2^{n/2}} \sum_{y=0}^{2^n-1} e^{2i\pi \frac{xy}{2^n}} |y\rangle \]
در این نمایش، جمع عدد کلاسیک Y را میتوان با n گیت چرخش فاز که روی n کیوبیت رجیستر عمل میکنند، پیادهسازی کرد.
\[ \prod_{i=0}^{n-1} P\left(2\pi Y\frac{2^i}{2^n}\right) QFT|x\rangle = QFT|(x + Y) \, \text{mod} \, 2^n \rangle \]
بنابراین، استراتژی این است که چرخشهای فازی را بین یک QFT و یک QFT -1 قرار دهیم تا جمع را پیادهسازی کنیم.
\[ |(x + Y)\, \text{mod}\, 2^n \rangle = QFT^{-1} \prod_{i=0}^{n-1} P\left(2\pi Y\frac{2^i}{2^n}\right) QFT |x\rangle \]
پیادهسازی جمع کنترلشده با جایگزینی گیتهای فاز با گیتهای فاز کنترلشده حاصل میشود.
در حالی که تعداد گیتهای ابتدایی در عملیات QFT و QFT -1 زیاد است، در واقع O(n ^2 )، جمع بعدی در فضای فوریه فقط به n گیت فاز نیاز دارد که میتوانند به صورت موازی عمل کنند. چندین جمع یا جمع کنترلشده را میتوان به صورت متوالی در طول اجرای یک مدار کوانتومی پیادهسازی کرد، در حالی که عدد صحیح کوانتومی x در فضای فوریه از طریق دنبالهای از چرخشهای فاز (کنترلشده) نمایش داده میشود. علاوه بر این، کل گیت جمعکننده QFT به کوبیتهای کمکی نیاز ندارد. این امر رویکرد QFT را به انتخابی ترجیحی در بسیاری از پروژههایی که به مدارهای جمعکننده کوانتومی نیاز دارند، تبدیل میکند.
یک بررسی اخیر توسط اس. وانگ و همکارانش [5] الگوریتمهای پیشرفته مختلف برای محاسبات کوانتومی را مقایسه میکند و کتابشناسی گستردهای در مورد این موضوع ارائه میدهد.
لازم به ذکر است که عملیات جمع شرح داده شده در بالا همیشه به پیمانه 2n است . این همانطور که انتظار میرفت، زیرا ما فقط میتوانیم اعداد صحیح در محدوده [0، 2n) را با n کیوبیت نمایش دهیم . بنابراین عملیاتی که تاکنون پیادهسازی شده است به صورت زیر است:
\[ \text{add}(Y): \quad |x\rangle_n \rightarrow |x+Y\rangle_n := |(x + Y)\, \text{mod}\, 2^n \rangle_n \]
که در آن، اندیس n تعداد کیوبیتها در رجیستر کوانتومی را نشان میدهد.
مرحله بعدی پیادهسازی بخش «به پیمانه N» است. این کار اساساً دشوارتر است و نیاز به مجموعهای از جمعها و تفریقهای (کنترلشده) دارد. ایدههای اساسی در کار Beauregard [2] شرح داده شده است.
مراحل پیشنهادی توسط بورگارد، با 0 ≤ Y < N و 0 ≤ x < N، عبارتند از:
- با n = ⌈log2 ( N)⌉، حالت n+1 کیوبیت |x⟩ n+1 را در نظر بگیرید . این یک کیوبیت بیشتر از مقدار لازم برای نگهداری x است، یعنی یک کیوبیت «سرریز» با مقدار اولیه |0⟩ وجود دارد.
- با استفاده از عملگر جمع (YN)، YN را جمع کنید. اگر x+YN≥ 0 باشد، حاصل میشود |x+YN⟩ n+1 ، یا اگر x+YN < 0 باشد، حاصل میشود |2 n+1 -x+N)⟩.
- علامت x+YN را در یک کیوبیت جانبی |a⟩ محاسبه کنید. این کار از طریق یک گیت CNOT که روی |a⟩ عمل میکند و توسط باارزشترین بیت (یعنی بیت سرریز) رجیستر n+1 کیوبیتی کنترل میشود، انجام میشود. پس از این مرحله |a⟩ = |0⟩ اگر x+Y ≥ N و |a⟩ = |1⟩ اگر x+Y < N باشد.
- با استفاده از یک عملیات جمع کنترلشده (N)، N را دوباره به رجیستر n+1 کیوبیتی اضافه کنید، که روی |a⟩ کنترل میشود. حالت حاصل |(x + Y) mod N⟩|a⟩ است.
مراحل زیر امکان بازنشانی کیوبیت ancilla به حالت اولیه |0⟩ آن را فراهم میکند:
- با استفاده از عملیات add(-Y) عدد -Y را جمع کنید. پس از این مرحله، رجیستر n+1 در حالت |x⟩ خواهد بود اگر x + Y < N باشد، یا در حالت |2 n+1 +xN)⟩ خواهد بود اگر x+Y ≥ N باشد.
- بیت آنسیلا که روی باارزشترین بیت رجیستر n+1 کیوبیتی کنترل میشود را با یک گیت CNOT معکوس کنید. پس از این مرحله، بیت آنسیلا همیشه در حالت |a⟩ = |1⟩ است. ما آن را با عمل کردن با یک گیت NOT به |0⟩ بازنشانی میکنیم: |a⟩ = NOT|1⟩ = |0⟩.
- با استفاده از عملیات add(Y) ، Y را دوباره جمع کنید. این منجر به حالت نهایی |(x + Y) mod N⟩|0⟩ میشود.
این ممکن است کمی پیچیده به نظر برسد، اما مسلماً سادهترین الگوریتم کوانتومی است که تاکنون برای انجام جمع مدولار یافت شده است.
سه مرحله آخر، یعنی برگرداندن کیوبیت آنسیلا |a⟩ به حالت اولیه خود |0⟩، در صورتی که قرار باشد کیوبیت آنسیلا در عملیات جمع مدولار بعدی مجدداً استفاده شود، که در الگوریتم شور چنین است، مهم هستند. به طور جایگزین، میتوان از کیوبیتهای آنسیلا جدید برای هر جمع مدولار استفاده کرد و عمقها و تعداد گیتهای مدار کامل یافتن ترتیب را کاهش داد، به قیمت افزایش تعداد کیوبیتها. به حداقل رساندن تعداد کیوبیتها معمولاً هدف اصلی است، زیرا پردازندههای کوانتومی فعلی تعداد محدودی کیوبیت دارند (در ادامه بیشتر در این مورد صحبت خواهیم کرد).
پیادهسازی جمع مدولار کنترلشده با جایگزینی هر جمع/تفریق از فاکتور Y با یک جمع/تفریق کنترلشده حاصل میشود.
مرحله بعدی اجرای عملیات است
\[ |x\rangle |y\rangle -> |x\rangle|(y+Ax) \,\text{mod}\, N\rangle \]
که در آن 0 ≤ y < N یک عدد صحیح کوانتومی دیگر است. این کار با تجزیه جمع مدولار y ↦ (y + Ax) mod N به دنبالهای از جمعهای مدولار y ↦ (y + 2 i A) mod N انجام میشود که به صورت add(2 i A, N)|y⟩ = |(y + 2 i A) mod N⟩ پیادهسازی میشود و روی بیت i ام |x i ⟩ از x = Σ i x i 2 i کنترل میشود . همانطور که دیدیم، جمع مدولار به یک کیوبیت سرریز و یک کیوبیت کمکی نیاز دارد، بنابراین عملیات واقعی که ما با این دستورالعمل پیادهسازی میکنیم به صورت زیر است:
\[ V_A: |x\rangle_n |y\rangle_{n+1} |0\rangle \right arrow |x\rangle_n |(y+Ax) \, \text{mod}\, N\rangle_{n+1} |0\rangle \]
با زیرنویسهایی که تعداد کیوبیتها را نشان میدهند.
در نهایت عملیات U A با … محقق میشود.
\[
\begin{align}
U_A \, : \quad
|x\rangle_n |0\rangle_{n+1} |0\rangle &\rightarrow |x\rangle_n |Axe\,\text{mod}\, N\rangle_{n+1} |0\rangle \\
&\rangle_{n+1} |Axmo\n,\t |x\rangle_{n+1} |0\rangle \\
&\arrow |Axe\,\text{mod}\, N\rangle_n |0\rangle_{n+1} |0\rangle
\end{تراز کردن}
\]
مرحله اول عملیات V A است . مرحله دوم از گیتهای SWAP برای تبادل دو مجموعه n کیوبیتی استفاده میکند. توجه داشته باشید که کیوبیت سرریز حالت میانی تعویض نمیشود (در این مرحله در حالت |0> است). مرحله سوم عملیات V -B با B = A -1 ، معکوس A در Z N ، با استفاده از این واقعیت است که (x – BAx) mod N = (x – x) mod N = 0. این اولین و تنها جایی است که از شرط اینکه A و N اعداد صحیح هماول هستند استفاده میشود (در غیر این صورت B وجود ندارد).
با شمارش تعداد کیوبیتهای استفاده شده، میبینیم که عملیات کامل U A به 2n+2 کیوبیت نیاز دارد.
تحلیل پیچیدگی کوانتومی
«پیچیدگی» یک الگوریتم کوانتومی معمولاً بر حسب سه کمیت بیان میشود: تعداد کیوبیتهای استفادهشده، تعداد گیتهای استفادهشده و عمق مدار.
تعداد کیوبیتهای مورد استفاده، مفهوم واضحی است. این مفهوم از آن جهت اهمیت دارد که پردازندههای کوانتومی هنوز تعداد محدودی کیوبیت برای کار دارند (معمولاً تا سال ۲۰۲۵، صدها کیوبیت).
تعداد گیتها مفهومی مبهمتر است و اغلب به تعداد گیتهای تککوبیتی و دوکوبیتی مانند H، NOT، P، SWAP، CNOT اشاره دارد. این میتواند فریبنده باشد زیرا پیادهسازی فیزیکی این گیتها ممکن است به چندین گیت «فیزیکی» نیاز داشته باشد که نشاندهنده عملیات کیوبیتی پیادهسازی شده در سطح سختافزار هستند. معمولاً گیتهای دوکوبیتی، مانند SWAP و CNOT، بین کیوبیتهای دور از هم، به زنجیرهای از گیتهای دوکوبیتی فیزیکی نیاز دارند که روی کیوبیتهای همسایه عمل میکنند. تعداد گیتهای فیزیکی به «اتصال» پردازندههای کوانتومی بستگی دارد، یعنی اینکه کدام عملیات دوکوبیتی از نظر فیزیکی مجاز هستند. این عملیاتها مربوط به عملیات روی کیوبیتهای مجاور هستند. حتی گیتهای تککوبیتی، مانند گیت هادامارد، ممکن است به چندین گیت تککوبیتی فیزیکی نیاز داشته باشند.
از آنجایی که مجموعه گیتهای فیزیکی و اتصال سختافزاری از یک ارائهدهنده به ارائهدهنده دیگر متفاوت است، بیشتر تحقیقات دانشگاهی صرفاً بر شمارش تعداد گیتهای تککوبیتی و دوکوبیتی «اساسی» تمرکز دارند.
عمق مدار کوانتومی به تعداد عملیات متوالی روی کیوبیتها که برای رسیدن به مرحله اندازهگیری نهایی لازم است ، اشاره دارد. هرچه عملیات موازی بیشتری روی کیوبیتها وجود داشته باشد، عمق کمتر است. عمق را میتوان تقریباً به عنوان طول مدار در یک نمایش تصویری تجسم کرد. به حداقل رساندن عمق یک مدار کوانتومی مهم است زیرا انسجام کوانتومی کیوبیتها با عمق کاهش مییابد. هرچه عملیات متوالی بیشتری وجود داشته باشد، اجرای مدار قبل از اندازهگیری نتایج آن بیشتر طول میکشد و زمان بیشتری برای کیوبیتها وجود دارد تا با محیط تعامل داشته باشند و انسجام خود را از دست بدهند.
اگر نگاهی به پیادهسازی UA A خود بیندازیم ، میبینیم که به (حداقل) 2n+2 کیوبیت نیاز دارد. تعداد گیتهایی که استفاده کردهایم O(n₂₃) است ( ضریب n₃ از استفاده از گیت QFT حاصل میشود) و عمق O(n₃) است ( ضریب n از استفاده از گیت QFT حاصل میشود).
اگر از سادهسازی کیوبیت کنترلی ۱ استفاده کنیم، مدار یافتن ترتیب کامل به یک کیوبیت دیگر نیاز دارد و عملیات متوالی U A را با O(n) انجام میدهد ، بنابراین تعداد کل کیوبیتهای مورد نیاز 2n+3 (4n+2 اگر از مدار با 2n کیوبیت کنترلی استفاده کنیم) است، تعداد کل گیتها O(n4 ) و عمق O(n3 ) است .
یک سادهسازی استاندارد دیگر نیز وجود دارد که استفاده از یک تبدیل QFT تقریبی با استفاده از تنها O(n log n) گیت به جای O(n^ 2 ) است. این کار باعث میشود ارزیابی کسر یافتن ترتیب k/2 2n کمی کمتر دقیق باشد، اما همچنان برای اجرای الگوریتم شور با احتمال موفقیت بالا به اندازه کافی خوب است. این کار تعداد گیتها را به O(n^ 3 log n) کاهش میدهد .
بسیاری از مقالات تحقیقاتی با بهبودهای جزئی در این اعداد منتشر شدهاند، اما تا جایی که من میدانم، هیچ پیشرفت عمدهای حاصل نشده است.
در مجموع، هزینه اجرای الگوریتم، چه از نظر تعداد کیوبیتها و چه از نظر تعداد عملیات، چندجملهای در n است، که نوید الگوریتم شور بود و مزیت کوانتومی را در کار فاکتورگیری برای اعداد صحیح بسیار بزرگ N نشان میدهد.
شبیهسازیها و اجراها روی سختافزار کوانتومی IBM
تاکنون هر آنچه که مورد بحث قرار دادیم، نظری بود و ۲۰ سال پیش شناخته شده بود. امروزه چندین شرکت در تلاشند تا پردازندههای کوانتومی را توسعه دهند که در اصل بتوانند الگوریتم شور را اجرا کنند. به طور خاص، پلتفرم کوانتومی IBM امکان انجام تعداد محدودی از محاسبات کوانتومی را به صورت رایگان بر روی پردازندههای کوانتومی (QPU) با ۱۲۸ کیوبیت ارائه میدهد.
کیت توسعه نرمافزاری Qiskit رابط کاربری مناسبی برای پیادهسازی مدارهای کوانتومی، انجام شبیهسازیها و اجرای مدارها روی سختافزار کوانتومی IBM فراهم میکند. این پلتفرم آموزشی، مقدمهای بر Qiskit برای تازهواردان ارائه میدهد.
$ pip install qiskit qiskit-ibm-runtime qiskit-aer qiskit[visualization]
برای اجرای الگوریتم شور، ما از کتابخانه متنباز qiskit-shor استفاده میکنیم که توسط نویسنده این پست پیادهسازی شده است. از هر خوانندهای که علاقهمند به پیادهسازی دقیق آن است دعوت میکنیم تا نگاهی به مخزن لینکشده بیندازد.
رابط برنامهنویسی کاربردی qiskit-shor دو تابع دارد: find_order(A, N) که مدار یافتن ترتیب را اجرا میکند و مرتبه r از A را در ZN، همراه با توزیع خروجیهای اندازهگیری شده، برمیگرداند ، و find_factor(N) که الگوریتم Shor را به طور کامل اجرا میکند و در صورت یافتن، یک فاکتور از N را برمیگرداند.
برای افزایش شانس موفقیت، مدار یافتن ترتیب را بارها، بین ۱۰۰ تا ۱۰۰۰ بار، اجرا میکنیم و توزیعی از خروجیهای اندازهگیری شده را مشاهده میکنیم. از این توزیع، ۱۰ مقدار با بیشترین تکرار را برای استخراج ترتیب در نظر میگیریم.
این کتابخانه هم مدار یافتن ترتیب با ۲n کیوبیت کنترلی و هم نسخه بهینهشده با یک کیوبیت کنترلی را پیادهسازی میکند. با این حال، ما بیشتر از نسخه کمتر بهینه با ۲n کیوبیت کنترلی استفاده میکنیم، زیرا پلتفرم IBM محدودیتهای استفاده سختگیرانهتری برای مدارهایی که از عملیات جریان کنترلی استفاده میکنند، دارد.
شبیهسازیها
پس از کلون کردن مخزن qiskit-shor ، میتوانیم با استفاده از شبیهساز qiskit Aer، شبیهسازیها را اجرا کنیم. ما شبیهسازیها را بدون نویز اجرا میکنیم تا کد را آزمایش کنیم. ما فقط با اعداد صحیح کوچک کار خواهیم کرد زیرا شبیهسازی حالت کوانتومی تعداد زیادی کیوبیت در یک کامپیوتر کلاسیک از نظر محاسباتی فشرده است و ما فقط میخواهیم ارائه فوق را با مثالهای ساده نشان دهیم.
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.visualization import plot_distribution
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import SamplerV2 as AerSampler
from qiskit_shor.shor import find_order
aer_sim = AerSimulator()
pm = generate_preset_pass_manager(backend=aer_sim, optimization_level=1)
sampler = AerSampler()
# Find the order of 7 in Z_15.
r, dist = find_order(A=7, N=15, sampler=sampler, pass_manager=pm, num_shots=100)
plot_distribution(dist)
Start search for the order of 7 in Z_15
Found value 4 for order of 7 in Z_15.
تابع، مرتبه ۴ را برمیگرداند که صحیح است، ۷ ^۴ = ۱ به پیمانه ۱۵. توزیع خروجی چهار مقدار برای عدد صحیح k نشان میدهد: ۰۰۰۰۰۰۰۰۰، ۰۱۰۰۰۰۰۰، ۱۰۰۰۰۰۰۰، ۱۱۰۰۰۰۰۰، که به ترتیب مربوط به نمادگذاری دودویی اعداد صحیح ۰، ۲^ ۶ ، ۲ ^۷ و ۲^ ۶ +۲^ ۷ هستند. خروجی دارای ۲n=۸ کیوبیت است که n=⌈log₂ ( ۱۵)⌉=۴ است. توزیع کسرهای تقریبی k/∈∈ دارای مقادیر ۰، ۱/۴، ۱/۲، ۳/۴ با تعداد تکرار مشابه است. این مقادیر با تخمین فازهای مورد انتظار j/∈، j=۰، ۱، ۲، ۳ از عملگر U₂ مطابقت دارند . مخرج مشترک ۴ این کسرها، مرتبه ۷ را در Z₂۱۵ به ما میدهد .
بیایید به مثال دوم نگاه کنیم و به دنبال مرتبه ۵ در Z21 بگردیم .
r, dist = find_order(A=5, N=21, sampler=sampler, pass_manager=pm, num_shots=500)
plot_distribution(dist)
Start search for the order of 5 in Z_21
Found value 6 for the order of 5 in Z_21.
جستجوی کوانتومی مقدار صحیح ۶ را برمیگرداند. توزیع خروجیها نتایج بیشتری دارد و مهمتر از همه، برخی از پیکها را نشان میدهد. با جایگزینی برچسبهای دستههای هیستوگرام با کسرهای مربوطه k/2 10 (گرد شده تا ۴ رقم اعشار)، هیستوگرام به صورت زیر در میآید .
میبینیم که در نقاط ۰، ۱/۶، ۱/۳، ۱/۲، ۲/۳ و ۵/۶ پیکهایی وجود دارد که همگی مقادیری به شکل j/6 هستند، j = 0، ۱، ۲، ۳، ۴، ۵ (پیکها در شکل به طور منظم با فاصله ظاهر نمیشوند، به دلیل حذف شدن مقادیر صفر). مقادیر j/6 مطابق با مقادیر ویژه عملگر واحد U5 هستند ، که ۶ در Z21 از مرتبه ۵ است ، همانطور که انتظار میرفت.
میتوانیم الگوریتم کامل را برای کامل بودن شبیهسازی کنیم و عوامل غیربدیهی را برای N=15 و N=21 استخراج کنیم. کد زیر الگوریتم شور را با حداکثر ۳ مقدار آزمایشی برای A اجرا میکند و در صورت یافتن عاملی به اندازه N متوقف میشود. هر آزمایش شامل اجرای ۱۰۰ بار مدار یافتن ترتیب است.
from qiskit_shor.shor import find_factor
f = find_factor(
N=15, sampler=sampler, pass_manager=pm, num_tries=3, num_shots_per_trial=100
)
Start search for the order of 4 in Z_15
Found value 2 for the order of 4 in Z_15
Factor found: 3
مقدار A=4 به صورت تصادفی انتخاب شد، سپس مرتبه ۲ پیدا شد، در نهایت ضریب ۳ از N=15 برگردانده شد.
f = find_factor(
N=21, sampler=sampler, pass_manager=pm, num_tries=3, num_shots_per_trial=100
)
Start search for the order of 17 in Z_21
Found value 6 for the order of 17 in Z_21
Start search for the order of 19 in Z_21
Found value 6 for the order of 19 in Z_21
Factor found: 3
ابتدا مقدار A=17 امتحان شد و مرتبه ۶ را به دست آورد، اما gcd(A r/2 – 1, N) = gcd(4912, 21) = 1 است، بنابراین ضریب ۲۱ را نمیدهد. در مرحله بعد مقدار ۱۹ امتحان شد و دوباره مرتبه ۶ را به دست آورد. این بار gcd(A r/2 – 1, N) = gcd(6858, 21) = 3 است که ضریب ۳ از ۲۱ را میدهد.
اجراهای کوانتومی
اکنون که متقاعد شدیم مدار یافتن ترتیب به درستی پیادهسازی شده است، میتوانیم آن را روی QPUهای واقعی اجرا کنیم.
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler
# For this to run, you need to setup an IBM Cloud account and generate
# an API token. See https://cloud.ibm.com
# Load default saved credentials
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
print(f"backend: {backend.name}")
pm = generate_preset_pass_manager(target=backend.target, optimization_level=1)
sampler = Sampler(mode=backend)
backend: ibm_brisbane
اکنون سعی میکنیم مانند شبیهسازی بالا، مرتبه ۷ را در Z15 پیدا کنیم .
r, dist = find_order(A=7, N=15, sampler=sampler, pass_manager=pm, num_shots=1000)
plot_distribution(dist)
Start search for the order of 7 in Z_15
Found value 4 for order of 7 in Z_15
ترتیب صحیح ۴ از ۷ در Z 15 برگردانده میشود، اما توزیع نتایج با توزیع نتایج در شبیهسازی که تنها ۴ مقدار مشاهده شده داشت، فاصله زیادی دارد. در اینجا تقریباً تمام مقادیر بین ۰ و ۲ ۸ -۱ ظاهر میشوند و نمودار را نسبتاً ناخوانا میکنند. برخی پیکهای کوچک وجود دارد، اما نتیجه تا حد زیادی تحت تأثیر نویز است. اینکه الگوریتم قادر است از بین ۱۰ مقدار پرتکرار، ترتیب صحیح را استخراج کند، تا حدودی معجزهآسا است.
اجراهای دیگر برای مقادیر مختلف A، برای N=15 یا N=21، دادههای نویزی مشابهی تولید میکنند. دلیل این امر آن است که سختافزار کوانتومی در معرض نویز کوانتومی است که با عملیات گیتهای واحد تداخل میکند. هرچه گیتهای بیشتری وجود داشته باشد، نویز بیشتری وجود دارد. در مدار یافتن مرتبه N=15، پیادهسازی ما در حال حاضر 2482 گیت دارد. این برای ظرفیتهای محاسبات کوانتومی فعلی بسیار زیاد است.
from qiskit_shor.shor import order_finding_circuit
qc = order_finding_circuit(A=7, N=15)
print(f"Number of qubits: {qc.num_qubits}") # 4n+2 qubits, with n = ceil(log2(N)) = 4
print(f"Number of gates: {qc.size()}")
print(f"Circuit depth: {qc.depth()}")
Number of qubits: 18
Number of gates: 2482
Circuit depth: 1632
میتوانیم با استفاده از مدار بهینهسازیشدهی تککنترلی کیوبیت، با جستجوی مرتبهی ۵ در Z6، حالتی با کیوبیتهای کمتر را امتحان کنیم .
from qiskit_shor.shor import order_finding_circuit_one_control
qc = order_finding_circuit_one_control(A=5, N=6)
print(f"Number of qubits: {qc.num_qubits}") # 2n+3 qubits, with n = ceil(log2(N)) = 3
print(f"Number of gates: {qc.size()}")
print(f"Circuit depth: {qc.depth()}")
Number of qubits: 9
Number of gates: 1246
Circuit depth: 861
r, dist = find_order(A=5, N=6, sampler=sampler, pass_manager=pm, num_shots=1000, one_control_circuit=True)
plot_distribution(dist)
Start search for the order of 5 in Z_6
Found value 2 for the order of 5 in Z_6
ترتیب صحیح ۲ برگردانده میشود، اما توزیع همچنان تحت سلطه نویز کوانتومی است.
نتیجهگیری
ما یک ارائه آزمایشی کامل از پیادهسازی الگوریتم شور، شامل شرحی تا حدودی مفصل از عملیات حسابی پیمانهای کوانتومی مربوطه، ارائه دادهایم. با استفاده از پیادهسازی ماژول qiskit-shor ، برخی شبیهسازیها و برخی محاسبات کوانتومی واقعی را روی پلتفرم IBM Quantum اجرا کردهایم. مشخص شد که محاسبات کوانتومی تحت سلطه نویز کوانتومی هستند و فعلاً اجرای الگوریتم شور و استخراج نتایج معنادار را غیرممکن میسازند.
پیادهسازی مورد استفاده ما ساده بود، به این معنا که شامل بهینهسازی پیشرفته نبود. اما خروجیهای نویزی مشاهده شده از این پیادهسازی ساده هنگام اجرای الگوریتم شور برای مقادیر بسیار کوچک N، نشان میدهد که حتی با بهینهسازیهای مدار اضافی، نتایج مشابهی به دست خواهد آمد.
در آینده ممکن است اجرای موفقیتآمیز الگوریتم شور واقعبینانهتر شود. پیشرفت عظیم در ظرفیتهای سختافزار کوانتومی در سالهای اخیر، امیدهای خوبی را برای دیدن این اتفاق در چند سال آینده به ما میدهد.